[
  {
    "path": ".editorconfig",
    "content": "root = true\n\n[*]\nindent_style = tab\nend_of_line = lf\ncharset = utf-8\ntrim_trailing_whitespace = true\ninsert_final_newline = true\n\n[*.md]\ntrim_trailing_whitespace = false\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/bug.yml",
    "content": "---\nname: \"Bug\"\ndescription: \"Report a bug found in the CLI\"\ntitle: \"(short issue description)\"\nlabels: [bug,needs-triage]\nassignees: [mwwoda, mhagmajer, antusus, arjankowski, lukaszsocha2, bartlomiejleszczynski, congminh1254]\nbody:\n  - type: checkboxes\n    id: sdk-docs-checked\n    attributes:\n      label: I have checked that the SDK documentation doesn't solve my issue.\n      description: <a href=\"/docs\">SDK documentation</a> link\n      options:\n        - label: Yes I've checked them.\n          required: true\n  - type: checkboxes\n    id: api-docs-checked\n    attributes:\n      label: I have checked that the API documentation doesn't solve my issue.\n      description: <a href=\"https://developer.box.com/docs\">API documentation</a> link\n      options:\n        - label: Yes I've checked them.\n          required: true\n  - type: checkboxes\n    id: dev-forums-checked\n    attributes:\n      label: I have checked that the Box Developer Forums doesn't solve my issue.\n      description: <a href=\"https://community.box.com/t5/Platform-and-Development-Forum/bd-p/DeveloperForum\">Box Developer Forums</a> link\n      options:\n        - label: Yes I've checked them.\n          required: true\n  - type: checkboxes\n    id: github-repo-checked\n    attributes:\n      label: I have searched Issues in this repo and my issue isn't already reported.\n      description: <a href=\"https://github.com/box/boxcli/search?type=Issues\">Github issues</a> link\n      options:\n        - label: Yes I've checked them.\n          required: true\n  - type: textarea\n    id: description\n    attributes:\n      label: Describe the bug\n      description: |\n        Please include as much detail as possible to help us troubleshoot!\n        - Share the full error output you're seeing, if applicable.\n        - Please include the full stack trace to help us identify where the error is happening.\n    validations:\n      required: true\n  - type: textarea\n    id: expected-behaviour\n    attributes:\n      label: Expected behavior\n      description: What did you expect to happen?\n    validations:\n      required: true\n  - type: textarea\n    id: steps-to-reproduce\n    attributes:\n      label: Steps to reproduce\n      description: |\n        Steps to reproduce the problem help speed up debugging for us and gets your issue resolved sooner!\n        The code sample should be an SSCCE. See http://sscce.org/ for details.\n        Please provide a code sample that we can copy/paste, run and reproduce.\n    validations:\n      required: true\n  - type: dropdown\n    id: authentication\n    attributes:\n      label: Authentication method used in your application\n      description: It can be found in your Application Configuration -> Configuration (TAB) -> Authentication Method\n      options:\n        -\n        - Server Authentication (with JWT)\n        - User Authentication (OAuth 2.0)\n        - Server Authentication (Client Credentials Grant)\n        - Developer Token\n    validations:\n      required: true\n  - type: dropdown\n    id: app-access-level\n    attributes:\n      label: App Access Level\n      description: It can be found in your Application Configuration -> Configuration (TAB) -> App Access Level\n      options:\n        -\n        - App Access Only\n        - App + Enterprise Access\n    validations:\n      required: true\n  - type: input\n    id: cli-version\n    attributes:\n      label: What is Box CLI Version and Node used?\n      placeholder: box --version\n    validations:\n      required: true\n  - type: input\n    id: os-version\n    attributes:\n      label: What is your Operating  System Version?\n    validations:\n      required: true\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/config.yml",
    "content": "blank_issues_enabled: false\ncontact_links:\n  - name: SDK documentation\n    url: https://github.com/box/boxcli/tree/main/docs\n    about: Before creating an issue, I have checked that the SDK documentation doesn't solve my issue.\n  - name: API documentation\n    url: https://developer.box.com/docs\n    about: Before creating an issue, I have checked that the API documentation doesn't solve my issue.\n  - name: Box Developer Forums\n    url: https://community.box.com/t5/Platform-and-Development-Forum/bd-p/DeveloperForum\n    about: Before creating an issue, I have searched the Box Developer Forums and my issue isn't already reported there.\n  - name: Issues in this repo\n    url: https://github.com/box/boxcli/search?type=Issues\n    about: Before creating an issue, I have searched Issues in this repo and my issue isn't already reported.\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/enhancement.md",
    "content": "---\nname: Enhancement\nabout: Suggest a new feature or change\ntitle: ''\nlabels: enhancement\nassignees: mwwoda, mhagmajer, antusus, arjankowski, lukaszsocha2, bartlomiejleszczynski\n\n---\n\n### Is your feature request related to a problem? Please describe.\n<!-- A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] -->\n\n### Describe the solution you'd like\n<!-- A clear and concise description of what you want to happen. -->\n\n### Describe alternatives you've considered\n<!-- A clear and concise description of any alternative solutions or features you've considered. -->\n\n### Additional context\n<!-- Add any other context or screenshots about the feature request here. -->\n"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/question.md",
    "content": "---\nname: Question\nabout: Request for Assistance\ntitle: ''\nlabels: question\nassignees: mwwoda, mhagmajer, antusus, arjankowski, lukaszsocha2, bartlomiejleszczynski\n\n---\n\n- [ ] I have checked that the [SDK documentation][sdk-docs] doesn't solve my issue.\n- [ ] I have checked that the [API documentation][api-docs] doesn't solve my issue.\n- [ ] I have searched the [Box Developer Forums][dev-forums] and my issue isn't already reported (or if it has been reported, I have attached a link to it, for reference).\n- [ ] I have searched [Issues in this repo][github-repo] and my issue isn't already reported.\n\n### Description of the Issue\n<!-- Replace this text with a description of what problem you're having. -->\n<!-- Please include as much detail as possible to help us troubleshoot! -->\n<!-- If it isn't obvious, please include how the behavior you expect differs from what actually happened. -->\n<!-- This is really important so we know how to start troubleshooting your issue. -->\n\n### Steps to Reproduce\n<!-- Please include detailed steps to reproduce the issue you're seeing, if possible. -->\n<!-- If you don't have a reproducible error, please make sure that you give us as much detail -->\n<!-- as you can about what your application was doing when the error occurred. -->\n<!-- Good steps to reproduce the problem help speed up debugging for us and gets your issue resolved sooner! -->\n1. Go to '...'\n2. Click on '....'\n3. Scroll down to '....'\n4. See error\n\n### Expected Behavior\n<!-- What did you expect to happen? -->\n\n### Error Message, Including Stack Trace\n<!-- Share the full error output you're seeing, if applicable. -->\n<!-- Please include the full stack trace to help us identify where the error is happening. -->\n\n### Screenshots\n<!-- If applicable, add screenshots to help explain your problem. -->\n\n### Versions Used\nBox CLI: <!-- Replace with the version of the Box CLI you're using. -->\nOperating System: <!-- Replace with the operating system you run the CLI on. -->\n\n[sdk-docs]: ./doc\n[api-docs]: https://developer.box.com/docs\n[dev-forums]: https://community.box.com/t5/Platform-and-Development-Forum/bd-p/DeveloperForum\n[github-repo]: https://github.com/box/boxcli/search?type=Issues\n"
  },
  {
    "path": ".github/stale.yml",
    "content": "# Number of days of inactivity before an issue becomes stale\ndaysUntilStale: 30\n\n# Number of days of inactivity before a stale issue is closed\ndaysUntilClose: 7\n\n# Issues or Pull Requests with these labels will never be considered stale. Set to `[]` to disable\nexemptLabels:\n  - enhancement\n  - dontstale\n  - needs-triage\n\n# Label to use when marking an issue as stale\nstaleLabel: stale\n\n# Comment to post when marking an issue as stale. Set to `false` to disable\nmarkComment: >\n  This issue has been automatically marked as stale because it has not been updated in the last 30 days. It will be closed if no further activity occurs within the next 7 days. Feel free to reach out or mention Box SDK team member for further help and resources if they are needed.\n\n# Comment to post when closing a stale issue. Set to `false` to disable\ncloseComment: >\n  This issue has been automatically closed due to maximum period of being stale. Thank you for your contribution to Box CLI and feel free to open another PR/issue at any time.\n"
  },
  {
    "path": ".github/workflows/build_and_test.yml",
    "content": "name: build-main\non:\n  pull_request:\n    types: [opened, synchronize]\n    branches:\n      - main\n  push:\n    branches:\n      - main\n\npermissions:\n  contents: read\n\njobs:\n  build-and-test:\n    runs-on: ${{ matrix.os }}\n    strategy:\n      fail-fast: false\n      matrix:\n        os: [ubuntu-latest, windows-latest, macos-latest]\n        node: ['18', '20', '22']\n    name: Node ${{ matrix.node }} on ${{ matrix.os }}\n    steps:\n      - name: Checkout\n        uses: actions/checkout@v2\n      - name: Setup Node\n        uses: actions/setup-node@v2\n        with:\n          node-version: ${{ matrix.node }}\n      - name: npm install\n        run: npm install\n      - name: Build and test\n        run: npm test\n      - name: Coveralls Parallel\n        uses: coverallsapp/github-action@master\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          flag-name: run-node-${{ matrix.node }}-${{ matrix.os }}\n          parallel: true\n  finish:\n    needs: build-and-test\n    runs-on: ubuntu-latest\n    steps:\n      - name: Coveralls Finished\n        uses: coverallsapp/github-action@master\n        with:\n          github-token: ${{ secrets.GITHUB_TOKEN }}\n          parallel-finished: true\n"
  },
  {
    "path": ".github/workflows/releases.yml",
    "content": "# A GitHub action that notifies the developer\n# changelog repository of any new releases.\n\nname: Notify changelog\n\non:\n  # Only trigger for a full release,\n  # ignoring pre-releases and drafts\n  release:\n    types:\n      - released\n\npermissions:\n  contents: read\n\njobs:\n  notify:\n    # This job can run on the latest Ubuntu\n    # and it should not take more than 3 minutes\n    runs-on: ubuntu-latest\n    timeout-minutes: 3\n\n    steps:\n      # There's really only 1 step, and i\n      - name: Notify changelog of new release\n        uses: peter-evans/repository-dispatch@v1\n        with:\n          token: ${{ secrets.DISPATCH_ACCESS_TOKEN }}\n          repository: box/box-developer-changelog\n          event-type: new-release-note\n          client-payload: '{\"ref\": \"${{ github.ref }}\", \"repository\": \"${{github.repository}}\", \"labels\": \"cli\", \"repo_display_name\": \"Box CLI\"}'\n"
  },
  {
    "path": ".github/workflows/semantic-pr.yml",
    "content": "name: Semantic PR\n\non:\n  pull_request_target:\n    types:\n      - opened\n      - edited\n      - synchronize\n\npermissions:\n  pull-requests: read\n\njobs:\n  main:\n    name: Validate semantic PR title\n    runs-on: ubuntu-latest\n    steps:\n      - uses: amannn/action-semantic-pull-request@v4\n        env:\n          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}\n"
  },
  {
    "path": ".github/workflows/spell-check-lint.yml",
    "content": "name: spell-check-lint\non:\n  pull_request_target:\n    types: [opened, synchronize, edited]\n    branches:\n      - main\n\npermissions:\n  contents: read\n\njobs:\n  spellcheck-request-title:\n    runs-on: ubuntu-latest\n    steps:\n      - name: Checkout current repository\n        uses: actions/checkout@v2\n      - name: Checkout spellchecker\n        uses: actions/checkout@v2\n        with:\n          ref: refs/heads/main\n          repository: box/box-sdk-spellchecker\n          token: ${{ secrets.DISPATCH_ACCESS_TOKEN }}\n          path: spellchecker\n      - name: Execute spellchecker\n        uses: ./spellchecker\n"
  },
  {
    "path": ".gitignore",
    "content": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\nlogs.json\n\n# Runtime data\npids\n*.pid\n*.seed\n*.pid.lock\n\n# Directory for instrumented libs generated by jscoverage/JSCover\nlib-cov\n\n# Coverage directories used by tools like nyc\n.nyc_output\ncoverage/\n\n# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)\n.grunt\n\n# Bower dependency directory (https://bower.io/)\nbower_components\n\n# node-waf configuration\n.lock-wscript\n\n# Compiled binary addons (http://nodejs.org/api/addons.html)\nbuild/Release\n\n# distribution folder\ndist/\n\n# Dependency directories\nnode_modules/\njspm_packages/\n\n# Typescript v1 declaration files\ntypings/\n\n# Optional npm cache directory\n.npm\n\n# Optional eslint cache\n.eslintcache\n\n# Optional REPL history\n.node_repl_history\n\n# Output of 'npm pack'\n*.tgz\n\n# Yarn Integrity file\n.yarn-integrity\n\n# dotenv environment variables file\n.env\n\n# Internal Use Files\n.DS_Store\n\n# Visual Studio Code config files\n.vscode\n\n# NVM files\n.nvmrc\n\n#Intelij Idea\n*.iml\n.idea\n\n# Oclif Build files\ntmp/\n"
  },
  {
    "path": ".glf",
    "content": "{\n  \"inputs\": [\"./package.json\"],\n  \"output\": \"./LICENSE-THIRD-PARTY.txt\",\n  \"lineEnding\": \"lf\",\n  \"replace\": {\n    \"rc@1.2.8\": \"./LICENSE.MIT\",\n    \"through@2.3.8\": \"./LICENSE.MIT\"\n  }\n}"
  },
  {
    "path": ".mocharc.yml",
    "content": "recursive: true\ntimeout: '10000'\nreporter: 'spec'"
  },
  {
    "path": ".nycrc",
    "content": "{\n\t\"include\": \"src/**/*.js\",\n\t\"all\": true,\n\t\"reporter\": [\n\t\t\"text-summary\",\n\t\t\"lcov\",\n\t\t\"html\"\n\t],\n\t\"check-coverage\": true,\n\t\"lines\": 80,\n\t\"statements\": 80,\n\t\"functions\": 80,\n\t\"branches\": 70,\n\t\"report-dir\": \"./coverage\"\n}\n"
  },
  {
    "path": ".prettierignore",
    "content": "test/fixtures/**\npackage.json\npackage-lock.json"
  },
  {
    "path": ".prettierrc.js",
    "content": "// prettier.config.js, .prettierrc.js, prettier.config.cjs, or .prettierrc.cjs\n\n/**\n * @see https://prettier.io/docs/configuration\n * @type {import(\"prettier\").Config}\n */\nconst config = {\n\ttrailingComma: 'es5',\n\ttabWidth: 4,\n\tsemi: true,\n\tsingleQuote: true,\n\toverrides: [\n\t\t{\n\t\t\tfiles: '*.json',\n\t\t\toptions: {\n\t\t\t\tuseTabs: false,\n\t\t\t},\n\t\t},\n\t],\n};\n\nmodule.exports = config;\n"
  },
  {
    "path": ".versionrc",
    "content": "{\n  \"types\": [\n    {\"type\": \"feat\", \"section\": \"New Features and Enhancements\", \"hidden\": false},\n    {\"type\": \"fix\", \"section\": \"Bug Fixes\", \"hidden\": false},\n    {\"type\": \"chore\", \"hidden\": true},\n    {\"type\": \"docs\", \"hidden\": true},\n    {\"type\": \"style\", \"hidden\": true},\n    {\"type\": \"refactor\", \"hidden\": true},\n    {\"type\": \"test\", \"hidden\": true}\n  ]\n}\n"
  },
  {
    "path": "CHANGELOG.md",
    "content": "# Changelog\n\nAll notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.\n\n## [4.8.0](https://github.com/box/boxcli/compare/v4.7.0...v4.8.0) (2026-04-23)\n\n\n### New Features and Enhancements\n\n* Add `--raw-json` flag and fix `--json` output ([#669](https://github.com/box/boxcli/issues/669)) ([ee6d61d](https://github.com/box/boxcli/commit/ee6d61d576e5cb037cf1b080f49ddfbd181eee09))\n* Add support for `Box Hub Collaborations` endpoints ([#668](https://github.com/box/boxcli/issues/668)) ([543cd60](https://github.com/box/boxcli/commit/543cd60b0f5532bb307aefc2291c0d051e8481bb))\n* Add support for `Box Hub Document` endpoints ([#667](https://github.com/box/boxcli/issues/667)) ([2b21328](https://github.com/box/boxcli/commit/2b213285ee8d6205a8461756231beb372ca81059))\n* Add support for `Box Hub Items` endpoints ([#665](https://github.com/box/boxcli/issues/665)) ([0f46680](https://github.com/box/boxcli/commit/0f466800a65ad9d57c20057f86f2410e8343493f))\n* Add support for `Box Hubs` endpoints ([#664](https://github.com/box/boxcli/issues/664)) ([681b312](https://github.com/box/boxcli/commit/681b31256592bbde00ffc4426917911f51fd951c))\n\n## [4.7.0](https://github.com/box/boxcli/compare/v4.6.0...v4.7.0) (2026-03-26)\n\n\n### New Features and Enhancements\n\n* Mask client secret in configure environments command ([#654](https://github.com/box/boxcli/issues/654)) ([ba62245](https://github.com/box/boxcli/commit/ba622459bc9d7808cdd412dd92d39a2a68caeb67))\n* Secure OAuth callback handling ([#653](https://github.com/box/boxcli/issues/653)) ([307d181](https://github.com/box/boxcli/commit/307d181d35b94aa5a6cced2f1ec211b1e0b42459))\n\n### Bug Fixes\n\n* Fix `oss` command ([#650](https://github.com/box/boxcli/issues/650)) ([63959c6](https://github.com/box/boxcli/commit/63959c646f5634dd6723826ba739ec564971cbb5))\n\n## [4.6.0](https://github.com/box/boxcli/compare/v4.5.0...v4.6.0) (2026-03-17)\n\n\n### New Features and Enhancements\n\n* Add `--overwrite` flag to `files:upload` command ([#637](https://github.com/box/boxcli/issues/637)) ([6231663](https://github.com/box/boxcli/commit/6231663c3e79eacfd52bcfe399527e12d589adb0))\n* Add support for Box Official App in login command ([#638](https://github.com/box/boxcli/issues/638)) ([bcd6835](https://github.com/box/boxcli/commit/bcd6835fb631ef7cd88ba8545b42b177ed2b3644))\n* Improve developer and agent experience in `boxcli` commands ([#643](https://github.com/box/boxcli/issues/643)) ([fbc817f](https://github.com/box/boxcli/commit/fbc817f6e25c6f0236777473e8a3e3ef5241df13))\n* Improve login prompt ([#642](https://github.com/box/boxcli/issues/642)) ([a58ff34](https://github.com/box/boxcli/commit/a58ff34dde121285233c174785071057e04c13a6))\n* Store access token encrypted in secure storage ([#639](https://github.com/box/boxcli/issues/639)) ([bed6db3](https://github.com/box/boxcli/commit/bed6db362aa501cfa1b47d9db74f26456adfa1be))\n* Support logout command ([#635](https://github.com/box/boxcli/issues/635)) ([842e308](https://github.com/box/boxcli/commit/842e308f38af8351ea469dfb1ecd705304611dc0))\n* Unify secure storage backend across platforms ([#647](https://github.com/box/boxcli/issues/647)) ([6b2ed36](https://github.com/box/boxcli/commit/6b2ed36655f7e896ee5a41308b60c28594fe693c))\n\n### Bug Fixes\n\n* Fix encoding for example scripts on Windows ([#613](https://github.com/box/boxcli/issues/613)) ([0265e2a](https://github.com/box/boxcli/commit/0265e2a65c4a985404b07ef2f83f56a903be329d))\n* fix help commands ([#611](https://github.com/box/boxcli/issues/611)) ([7aec97b](https://github.com/box/boxcli/commit/7aec97b0a63d2c1b3496cb296cf6dddaf539a9aa))\n* Normalize inquirer `signal-exit` compatibility on Windows ([#645](https://github.com/box/boxcli/issues/645)) ([310b2f6](https://github.com/box/boxcli/commit/310b2f6ea07a856709b6a46454d1852fa66b7a66))\n\n## [4.5.0](https://github.com/box/boxcli/compare/v4.4.1...v4.5.0) (2025-11-20)\n\n\n### New Features and Enhancements\n\n* support auto update using Github releases ([#603](https://github.com/box/boxcli/issues/603)) ([2460e1b](https://github.com/box/boxcli/commit/2460e1b51002e94c3a16356099c4511faa96b87c))\n\n### Bug Fixes\n\n* update dependencies to fix `tmp` vulnerability ([#600](https://github.com/box/boxcli/issues/600)) ([7e270eb](https://github.com/box/boxcli/commit/7e270eb8daf254a64eb3ce373444e9ad96e5e5be))\n\n### [4.4.1](https://github.com/box/boxcli/compare/v4.4.0...v4.4.1) (2025-10-21)\n\n\n### Bug Fixes\n\n* Fix the `--exempt-from-2fa` flag in `create` and `update` users commands ([#598](https://github.com/box/boxcli/issues/598)) ([8f897fe](https://github.com/box/boxcli/commit/8f897feb677a0089e7854aaf8ef6b2babb70ab16))\n\n## [4.4.0](https://github.com/box/boxcli/compare/v4.3.1...v4.4.0) (2025-10-14)\n\n\n### New Features and Enhancements\n\n* Support update users notification email ([#596](https://github.com/box/boxcli/issues/596)) ([49356f4](https://github.com/box/boxcli/commit/49356f4ad954caf0c0d60646debc2bc047bddf7a))\n\n### [4.3.1](https://github.com/box/boxcli/compare/v4.3.0...v4.3.1) (2025-09-29)\n\n\n### Bug Fixes\n\n* Fix multi item mode in `ai:ask` command ([#593](https://github.com/box/boxcli/issues/593)) ([5081d43](https://github.com/box/boxcli/commit/5081d432d8ded16c8bf759352d28be0214fbe4ec))\n\n## [4.3.0](https://github.com/box/boxcli/compare/v4.2.0...v4.3.0) (2025-08-07)\n\n\n### New Features and Enhancements\n\n* add agent support to `ai:ask` command ([#589](https://github.com/box/boxcli/issues/589)) ([095f411](https://github.com/box/boxcli/commit/095f4110274f67c5b1024de49a256b5bbe35cf18))\n\n### Bug Fixes\n\n* Fix support metadata query array ([#583](https://github.com/box/boxcli/issues/583)) ([112db16](https://github.com/box/boxcli/commit/112db160230e5bb75f84e44cb86a8372341dd8ad))\n* Remove `description` flag from folders:create command ([#587](https://github.com/box/boxcli/issues/587)) ([adca76b](https://github.com/box/boxcli/commit/adca76b5fb03f62daf2104500b87f8a962382a35))\n\n## [4.2.0](https://github.com/box/boxcli/compare/v4.1.0...v4.2.0) (2025-06-20)\n\n\n### New Features and Enhancements\n\n* Setup proxy for Box CLI with TS SDK ([#577](https://github.com/box/boxcli/issues/577)) ([ec42077](https://github.com/box/boxcli/commit/ec4207715360cc284574e1cbb573586218379517))\n* Support `owned-by` flag when moving folder ([#580](https://github.com/box/boxcli/issues/580)) ([2ec8e7f](https://github.com/box/boxcli/commit/2ec8e7fcf241dcd2c5841b8912e178e2384db426))\n* Support integration mappings for Teams ([#579](https://github.com/box/boxcli/issues/579)) ([163a367](https://github.com/box/boxcli/commit/163a36727c5f76b0e3b1c36049b3abae50148eb6))\n* Support metadata query with array ([#581](https://github.com/box/boxcli/issues/581)) ([6750708](https://github.com/box/boxcli/commit/675070856eac6d06f2091203f4f19e41055dd97d))\n\n## [4.1.0](https://github.com/box/boxcli/compare/v4.0.1...v4.1.0) (2025-05-15)\n\n\n### New Features and Enhancements\n\n* Support AI Extract endpoints ([#574](https://github.com/box/boxcli/issues/574)) ([0b4ff6b](https://github.com/box/boxcli/commit/0b4ff6b63c8707c6842f3812d2a69071d195b799))\n\n### Bug Fixes\n\n* Remove invalid `process.stderr.setEncoding` call ([486779e](https://github.com/box/boxcli/commit/486779ee3b8403805286b7ae6d3ab5c802c6f948)), closes [#571](https://github.com/box/boxcli/issues/571)\n\n### [4.0.1](https://github.com/box/boxcli/compare/v4.0.0...v4.0.1) (2025-03-07)\n\n\n### Bug Fixes\n\n* Fix `configure:environments:set-current` command ([#568](https://github.com/box/boxcli/issues/568)) ([dc0905f](https://github.com/box/boxcli/commit/dc0905f7b85a32373e93ec7726afb261223e9fac))\n\n## [4.0.0](https://github.com/box/boxcli/compare/v3.16.0...v4.0.0) (2025-01-28)\n\n\n### ⚠ BREAKING CHANGES\n\n* Ended support for Node.js 14 & 16; added support for Node.js 20 & 22 ([#548](https://github.com/box/boxcli/issues/548)) ([22179ec](https://github.com/box/boxcli/commit/22179ecfc68b8dd315339ac204a7274d712d5a8e))\n\n### New Features and Enhancements\n\n* Incognito browser option for box login ([#561](https://github.com/box/boxcli/issues/561)) ([a666766](https://github.com/box/boxcli/commit/a6667664d6b43fd80de9e57482b0f4138efcd6cf))\n* Replace `@oclif/command` to `@oclif/core` library ([#553](https://github.com/box/boxcli/issues/553)) ([aed470b](https://github.com/box/boxcli/commit/aed470b22d28ed19040b4417e3143f3323b9a916))\n\n### Bug Fixes\n\n* Respect using environment `defaultAsUserId` for CCG Auth and OAuth ([#554](https://github.com/box/boxcli/issues/554)) ([b3a691e](https://github.com/box/boxcli/commit/b3a691e8c886f7bb3a25ae8f7986f284a695f046))\n\n## [3.16.0](https://github.com/box/boxcli/compare/v3.15.0...v3.16.0) (2024-11-25)\n\n\n### New Features and Enhancements\n\n* add support for `template_id` during sign request creation ([#549](https://github.com/box/boxcli/issues/549)) ([95963c1](https://github.com/box/boxcli/commit/95963c19650937f9d67c47184cc8a743166eae60))\n\n### Bug Fixes\n\n* Change zone name in the mass update user zone script ([#546](https://github.com/box/boxcli/issues/546)) ([1a1d603](https://github.com/box/boxcli/commit/1a1d603267b928e08df32394637f53264e9e57c9))\n\n## [3.15.0](https://github.com/box/boxcli/compare/v3.14.1...v3.15.0) (2024-08-06)\n\n\n### New Features and Enhancements\n\n* Support AI APIs using Box Node SDK ([#539](https://github.com/box/boxcli/issues/539)) ([59551d2](https://github.com/box/boxcli/commit/59551d2153549b5a87b2c3fae01eb3089d640c89))\n\n### [3.14.1](https://github.com/box/boxcli/compare/v3.14.0...v3.14.1) (2024-06-06)\n\n\n### Bug Fixes\n\n* Fix bulk action in `search` command ([#528](https://github.com/box/boxcli/issues/528)) ([782b0e6](https://github.com/box/boxcli/commit/782b0e6b00905d9724289cb05cf03a708c32ebb3))\n* Fix bulk operation for `sign-requests:create` command ([#531](https://github.com/box/boxcli/issues/531)) ([6d9cd6b](https://github.com/box/boxcli/commit/6d9cd6b82088185c1b98e8c4ed9ac26af4ee3362))\n\n## [3.14.0](https://github.com/box/boxcli/compare/v3.13.0...v3.14.0) (2024-03-06)\n\n\n### New Features and Enhancements\n\n* Add support for `vanity_name` when creating `shared-links` ([#524](https://github.com/box/boxcli/issues/524)) ([38164bc](https://github.com/box/boxcli/commit/38164bc716879aef0a8a2b973a9c6fc7eb705978))\n* Support sign request signer group ID ([#521](https://github.com/box/boxcli/issues/521)) ([f7b1b44](https://github.com/box/boxcli/commit/f7b1b4409e0f72c264cc23a0f1ca1849060bf121))\n\n## [3.13.0](https://github.com/box/boxcli/compare/v3.12.2...v3.13.0) (2024-02-22)\n\n\n### New Features and Enhancements\n\n* Add additional `UseDisplayName` flag to metadata extraction script ([#515](https://github.com/box/boxcli/issues/515)) ([b900fdb](https://github.com/box/boxcli/commit/b900fdb984345c0fdfeb09e531f6a358ad8c3b8e))\n* Add additional context info when throw exception ([#519](https://github.com/box/boxcli/issues/519)) ([b99a58d](https://github.com/box/boxcli/commit/b99a58d930eccf5363c82b84e4415336d7d69541))\n* Support overwrite/skip folder download ([#516](https://github.com/box/boxcli/issues/516)) ([300f914](https://github.com/box/boxcli/commit/300f914ba8bb94d9c399699d126d81aba0b22142))\n\n### Bug Fixes\n\n* Fix metadata extraction script ([#514](https://github.com/box/boxcli/issues/514)) ([2fad540](https://github.com/box/boxcli/commit/2fad540badf60538fe1456f8071b74bf917f7464))\n* Fix the functionality of the overwrite flag ([#513](https://github.com/box/boxcli/issues/513)) ([f4bf7af](https://github.com/box/boxcli/commit/f4bf7af8e0bbdf7e73fab23d920259ef16672be0))\n\n### [3.12.2](https://github.com/box/boxcli/compare/v3.12.1...v3.12.2) (2023-11-08)\n\n\n### Bug Fixes\n\n* Bump box-node-sdk ([#510](https://github.com/box/boxcli/issues/510)) ([2621f41](https://github.com/box/boxcli/commit/2621f4121999ff6e9d0cc0c391dfd3aa93aefe49))\n\n### [3.12.1](https://github.com/box/boxcli/compare/v3.12.0...v3.12.1) (2023-11-06)\n\n\n### Bug Fixes\n\n* force offset based pagination in get users ([#504](https://github.com/box/boxcli/issues/504)) ([9bed083](https://github.com/box/boxcli/commit/9bed083d59b2386d045619fdf2f3ea915e44d231))\n\n## [3.12.0](https://github.com/box/boxcli/compare/v3.11.0...v3.12.0) (2023-09-18)\n\n\n### New Features and Enhancements\n\n* Support sign templates ([#496](https://github.com/box/boxcli/issues/496)) ([955106f](https://github.com/box/boxcli/commit/955106ffa5d7938c567e5440868f2ec3c87045ce))\n\n## [3.11.0](https://github.com/box/boxcli/compare/v3.10.0...v3.11.0) (2023-09-05)\n\n\n### New Features and Enhancements\n\n* detect and exclude the byte order mark (BOM) from the CSV input if present ([#492](https://github.com/box/boxcli/issues/492)) ([e147919](https://github.com/box/boxcli/commit/e14791955b53be5c15f8580ee1f9841d8227803b))\n\n## [3.10.0](https://github.com/box/boxcli/compare/v3.9.2...v3.10.0) (2023-08-16)\n\n\n### New Features and Enhancements\n\n* Support update user tracking codes ([#489](https://github.com/box/boxcli/issues/489)) ([159e6d0](https://github.com/box/boxcli/commit/159e6d07fa91f2b199ca85207a4cad5cf4274f0e))\n\n### [3.9.2](https://github.com/box/boxcli/compare/v3.9.1...v3.9.2) (2023-08-08)\n\n\n### Bug Fixes\n\n* Fix escaped slashes when passing an input to command ([#486](https://github.com/box/boxcli/issues/486)) ([7670210](https://github.com/box/boxcli/commit/7670210ffb5c38cef8dd153e823029d5237080b6))\n\n### [3.9.1](https://github.com/box/boxcli/compare/v3.9.0...v3.9.1) (2023-07-19)\n\n\n## [3.9.0](https://github.com/box/boxcli/compare/v3.8.0...v3.9.0) (2023-06-02)\n\n\n### New Features and Enhancements\n\n* add `max-items`, improve list endpoints performance ([#470](https://github.com/box/boxcli/issues/470)) ([8f386f3](https://github.com/box/boxcli/commit/8f386f3b7c4ff4efbaa941321fd672694ce3c7a1))\n* Add support for Integration Mappings API ([#472](https://github.com/box/boxcli/issues/472)) ([bbf2548](https://github.com/box/boxcli/commit/bbf2548223e0d07ce2412c04991e7d8f00022fa7))\n* New fields in `retention-policy` and `retention-policy-assignment` ([#466](https://github.com/box/boxcli/issues/466)) ([f960e59](https://github.com/box/boxcli/commit/f960e59aaf55fe0a0507e9f4c9d867e7c3dd039a))\n\n## [3.8.0](https://github.com/box/boxcli/compare/v3.7.0...v3.8.0) (2023-03-03)\n\n\n### New Features and Enhancements\n\n* add alias for metadata cascade policy create ([#460](https://github.com/box/boxcli/issues/460)) ([8d2f683](https://github.com/box/boxcli/commit/8d2f683e092c036efe352e6fd70904083ad7c208))\n* Add support for `--reauthorize` flag in login command ([#457](https://github.com/box/boxcli/issues/457)) ([f653a0d](https://github.com/box/boxcli/commit/f653a0d526c7194f0a5e80dc837f0f16a9d4f27b))\n\n### Bug Fixes\n\n* Fix `keychain` access by bumping `keychain` library to `1.4.0` ([#459](https://github.com/box/boxcli/issues/459)) ([56919ce](https://github.com/box/boxcli/commit/56919cefabef6de4d96a1f69f7c80740a680876c))\n* Fix unit tests ([#456](https://github.com/box/boxcli/issues/456)) ([f89d9ef](https://github.com/box/boxcli/commit/f89d9ef5c3c4e7bf00c0be40f128428b1e7e6983))\n\n## [3.7.0](https://github.com/box/boxcli/compare/v3.6.0...v3.7.0) (2023-01-19)\n\n\n### New Features and Enhancements\n\n* Add more flags for folder update collaborators ([#438](https://github.com/box/boxcli/issues/438)) ([83ac6d7](https://github.com/box/boxcli/commit/83ac6d7c8eeb7f3dc8562c8132cade4f5af80ee1))\n* Add support session termination ([#446](https://github.com/box/boxcli/issues/446)) ([aef15a8](https://github.com/box/boxcli/commit/aef15a8d2c7ee904db320d879deb6ebf0f934d22))\n\n### Bug Fixes\n\n* Fix delete token cache from disk ([#445](https://github.com/box/boxcli/issues/445)) ([aafb68a](https://github.com/box/boxcli/commit/aafb68ae38a8280bd97cf978042a8df5b71b2f52))\n* Fix metadata template update when adding multiple options to enum ([#442](https://github.com/box/boxcli/issues/442)) ([8779eec](https://github.com/box/boxcli/commit/8779eecf24bda5b093bc891f5097879e1876b601))\n* single file upload on Node 16 ([#441](https://github.com/box/boxcli/issues/441)) ([d94ab35](https://github.com/box/boxcli/commit/d94ab35a38938daf4edbbd134774a3809facecbd))\n\n## [3.6.0](https://github.com/box/boxcli/compare/v3.5.0...v3.6.0) (2022-11-22)\n\n\n### New Features and Enhancements\n\n* Add `id` and `type` field  to shared-links:create response ([#427](https://github.com/box/boxcli/issues/427)) ([5ea4cb8](https://github.com/box/boxcli/commit/5ea4cb82294188dd30563ef9cea2c8e0b76bbfae))\n* Add fields disposition_at field for files under retention ([#429](https://github.com/box/boxcli/issues/429)) ([db824ef](https://github.com/box/boxcli/commit/db824ef0b4111810b7902896062c950ef9ac01b3))\n\n### Bug Fixes\n\n* Fix `event:poll` polling-interval ([#430](https://github.com/box/boxcli/issues/430)) ([9ada74b](https://github.com/box/boxcli/commit/9ada74b09eb5aa0e09881946a4f7f30e2d68e037))\n\n## [3.5.0](https://github.com/box/boxcli/compare/v3.4.0...v3.5.0) (2022-11-02)\n\n\n### New Features and Enhancements\n\n* Add option to change name of downloaded file in `save-as`parameter ([#415](https://github.com/box/boxcli/issues/415)) ([81fe64e](https://github.com/box/boxcli/commit/81fe64eb2891e7ab55564e2428f64f1129b468e8))\n* Add support for modifiable retention policies & enable deleting retention policy assignment ([#420](https://github.com/box/boxcli/issues/420)) ([26ab5b4](https://github.com/box/boxcli/commit/26ab5b4d7ec49576fdac48abc025903622f8efe0))\n\n## [3.4.0](https://github.com/box/boxcli/compare/v3.3.2...v3.4.0) (2022-09-26)\n\n\n### New Features and Enhancements\n\n* Add `DryRun` mode in `User Deprovision` example script ([#392](https://github.com/box/boxcli/issues/392)) ([584a30e](https://github.com/box/boxcli/commit/584a30ef33446a6687ce558c810804202650299f))\n* Add `redirect_url` and `declined_redirect_url` to Sign Request ([#395](https://github.com/box/boxcli/issues/395)) ([261b7d2](https://github.com/box/boxcli/commit/261b7d22a5e5adf3647276cbf59454cca9bf607f))\n* Add progress bar for file download and bulk command ([#376](https://github.com/box/boxcli/issues/376)) ([68359c7](https://github.com/box/boxcli/commit/68359c7e97ce2b606184426cbbaac73914ceb81a))\n* create destination path during download ([#393](https://github.com/box/boxcli/issues/393)) ([40881dd](https://github.com/box/boxcli/commit/40881ddbd2c86e80f19689f012736fb19f18d945))\n* native credentials storage for Windows with a new library ([#385](https://github.com/box/boxcli/issues/385)) ([a6918aa](https://github.com/box/boxcli/commit/a6918aaa6e28bd29619bea31c97b845d8d429fec))\n\n### Bug Fixes\n\n* correctly resolve home dir in folders download ([#398](https://github.com/box/boxcli/issues/398)) ([86d3230](https://github.com/box/boxcli/commit/86d3230456827a042be04f5ef372b15d83fd6a10))\n* Fix logs in `Users Deprovisioning` script ([#381](https://github.com/box/boxcli/issues/381)) ([c85f77b](https://github.com/box/boxcli/commit/c85f77b3042dfc3ddfe54b2acd94b220f6ee0e9b))\n* Fix problem with `keytar` library ([#394](https://github.com/box/boxcli/issues/394)) ([1979f01](https://github.com/box/boxcli/commit/1979f01758a30cd1dbf9d32c19ce2f3a00c0d5ec))\n\n### Note\n\n* To migrate storing Box CLI environments to the system credential storage, execute the following command in the terminal (https://github.com/box/boxcli/issues/295):\n  ```\n  box configure:environments:update\n  ```\n\n### [3.3.2](https://github.com/box/boxcli/compare/v3.3.1...v3.3.2) (2022-07-29)\n\n\n### Bug Fixes\n\n* Fix request command when calling without body ([#369](https://github.com/box/boxcli/issues/369)) ([9317888](https://github.com/box/boxcli/commit/9317888c3f1bff56ef784d7319f1b8ccf12239ef))\n\n### [3.3.1](https://github.com/box/boxcli/compare/v3.3.0...v3.3.1) (2022-07-25)\n\n\n### Bug Fixes\n\n* Fix OAuth login ([#364](https://github.com/box/boxcli/issues/364)) ([579b44b](https://github.com/box/boxcli/commit/579b44b83c60f6568c98cb5f1417effbac26c58c))\n\n## [3.3.0](https://github.com/box/boxcli/compare/v3.2.0...v3.3.0) (2022-07-19)\n\n\n### New Features and Enhancements\n\n* add editable shared link support ([#350](https://github.com/box/boxcli/issues/350)) ([ab639e7](https://github.com/box/boxcli/commit/ab639e7e9336e8745ef84dd6dfc646c987638ec3))\n* add file requests api support ([#355](https://github.com/box/boxcli/issues/355)) ([73f0490](https://github.com/box/boxcli/commit/73f0490ff3c3dfefb89e14dde933d3a3ffc4113f))\n* add possibility to set custom analytics header ([#348](https://github.com/box/boxcli/issues/348)) ([5a3387f](https://github.com/box/boxcli/commit/5a3387fb687bcbd5d8441117c497312ac1d20f27))\n* Support --copy-instance-on-item-copy flag for update metadata template ([#357](https://github.com/box/boxcli/issues/357)) ([5d8272a](https://github.com/box/boxcli/commit/5d8272a0559ec97a345a2032456998383e7a6716))\n* support Client Credentials Grant as authentication method ([#335](https://github.com/box/boxcli/issues/335)) ([4649d8a](https://github.com/box/boxcli/commit/4649d8adf39f64c8292b70c35b7bffa96e462edc))\n\n## [3.2.0](https://github.com/box/boxcli/compare/v3.1.0...v3.2.0) (2022-06-30)\n\n\n### New Features and Enhancements\n\n* Added support for stream type `admin_logs_streaming` ([#337](https://github.com/box/boxcli/issues/337)) ([7596157](https://github.com/box/boxcli/commit/7596157e3a72ef152be44a04198e38d6c57de250))\n\n### Bug Fixes\n\n* Fix native storage errors ([#345](https://github.com/box/boxcli/issues/345)) ([b73b841](https://github.com/box/boxcli/commit/b73b841224ad7f5bb543c92962adb7fc5960bb8c))\n\n## [3.1.0](https://github.com/box/boxcli/compare/v3.0.0...v3.1.0) (2022-06-17)\n\n\n### New Features and Enhancements\n\n* Add --all flag for search to return all results ([#336](https://github.com/box/boxcli/issues/336)) ([23ea0a5](https://github.com/box/boxcli/commit/23ea0a5c5b065ea3b91b73b64bb7b267a6ff0a18))\n* add unique state parameter to OAuth2 login ([#292](https://github.com/box/boxcli/issues/292)) ([5ce6a40](https://github.com/box/boxcli/commit/5ce6a40b4c6e2fc78b2b598a8b1529200c63902e))\n* allow changing base URLs ([#303](https://github.com/box/boxcli/issues/303)) ([e284059](https://github.com/box/boxcli/commit/e28405971ebcf2c2284bb875b40ceb7eaebb41c4))\n* obtain `oauth` authorization from commandline ([#299](https://github.com/box/boxcli/issues/299)) ([18c88bb](https://github.com/box/boxcli/commit/18c88bb6835509394b92eb0685e3a9306ede8984))\n* use native credential storage for MacOS and Windows ([#295](https://github.com/box/boxcli/issues/295)) ([74c4922](https://github.com/box/boxcli/commit/74c492271ebc54e15500abbaaa2c7aac32be5070))\n\n### Bug Fixes\n\n* `users:transfer-content` to respect quiet flag ([#288](https://github.com/box/boxcli/issues/288)) ([1d0bbab](https://github.com/box/boxcli/commit/1d0bbab652bf74a59c8486fc4d5eac415161254c))\n* correctly pass `copy-instance-on-item-copy` flag ([#285](https://github.com/box/boxcli/issues/285)) ([cd4fbf4](https://github.com/box/boxcli/commit/cd4fbf4f746b83c2b066efb31b2e2952dba1312d))\n* Fix updating webhook triggers ([#297](https://github.com/box/boxcli/issues/297)) ([09e94c3](https://github.com/box/boxcli/commit/09e94c32ed8e4243e76dd19e67b6d1c17c2cdc04))\n* support large output when using `json` flag by replacing `json.stringify` ([#328](https://github.com/box/boxcli/issues/328)) ([1204f2c](https://github.com/box/boxcli/commit/1204f2c146c713124060730e0554ab2f2dde27fa))\n* Support limit flag for Box Search ([#323](https://github.com/box/boxcli/issues/323)) ([0009a77](https://github.com/box/boxcli/commit/0009a77ee3fc4b72ef01bbbeff0ea588c10a6f89)), closes [#322](https://github.com/box/boxcli/issues/322)\n* Support OAuth with multiple redirect URIs ([#302](https://github.com/box/boxcli/issues/302)) ([9fe216e](https://github.com/box/boxcli/commit/9fe216e8d2f59e4375a4b7c766844366f7166a0a))\n\n## [3.0.0](https://github.com/box/boxcli/compare/v2.9.0...v3.0.0) (2022-01-27)\n\n### ⚠ BREAKING CHANGES\n\n- Drop support for Node 10\n- Insensitive language changes (#247, #252)\n\n### New Features and Enhancements\n\n- Add support for login with OAuth ([#240](https://github.com/box/boxcli/pull/240))\n- feat: support as-user flag for bulk files and when token is present ([#270](https://github.com/box/boxcli/pull/270))\n- Add support for copyInstanceOnItemCopy field for metadata templates  ([#239](https://github.com/box/boxcli/pull/239))\n- Add support note to the mdfilter equality check in search ([#253](https://github.com/box/boxcli/pull/253))\n- Add support for Box Sign API ([#258](https://github.com/box/boxcli/pull/258))\n- Add support Metadata Query API ([#259](https://github.com/box/boxcli/pull/259))\n- fix: folder:collaborations:add make role a required flag (SDK-1070) ([#261](https://github.com/box/boxcli/pull/261))\n- Minor dependencies upgrade\n- Add new API for files and file versions under retention (#250)\n- Adding support for sign request (#258)\n- Support Metadata Query API (#259)\n- chore: enforce conventional commits (#268)\n- feat: support as-user flag for bulk files and when token is present (#270)\n\n### Bug Fixes\n- fix: folder:collaborations:add make role a required flag (#261)\n- fix: Fixed shared-links delete example. (#262)\n\n## [2.9.0](https://github.com/box/boxcli/compare/v2.8.0...v2.9.0) (2021-02-22)\n\n### New Features and Enhancements\n\n- Add ability to add an option to a metadata template multi select field ([#230](https://github.com/box/boxcli/pull/230))\n- Add folder lock functionality ([#232](https://github.com/box/boxcli/pull/232))\n- Add support for search param to get shared link items ([#233](https://github.com/box/boxcli/pull/233))\n\n### Bug Fixes\n\n- Fix events command bug when there is no stream position flag ([#234](https://github.com/box/boxcli/pull/234))\n\n## [2.8.0](https://github.com/box/boxcli/compare/v2.7.0...v2.8.0) (2020-12-03)\n\n### Warning:\n\n- Due to the changes in ([#217](https://github.com/box/boxcli/pull/217)), additional details about Box Items may now be returned for some commands.\n\n### New Features and Enhancements\n\n- Output contents of array for bulk commands ([#217](https://github.com/box/boxcli/pull/217))\n\n### Bug Fixes\n\n- Fix bug with setting proxy settings ([#218](https://github.com/box/boxcli/pull/218))\n\n## [2.7.0](https://github.com/box/boxcli/compare/v2.6.0...v2.7.0) (2020-11-02)\n\n### New Features and Enhancements\n\n- Make commands `collaborations:add`, `shared-links:update`, `shared-links:delete`, `users:search` that were previously hidden, now available ([#211](https://github.com/box/boxcli/pull/211))\n- Add `filter_term` parameter to `groups:list` ([#210](https://github.com/box/boxcli/pull/210))\n\n### Bug Fixes\n\n- Fix bug with setting proxy settings ([#213](https://github.com/box/boxcli/pull/213))\n\n## [2.6.0](https://github.com/box/boxcli/compare/v2.5.1...v2.6.0) [2020-08-20]\n\n- Fix filename issue when saving reports on Windows\n- Add proxy support for `http`, `https`, `socks` and `pac` protocols. Proxy settings can be found under `box configure:settings`\n- Add zip functionality\n\n## [2.5.1](https://github.com/box/boxcli/compare/v2.4.0...v2.5.1) [2020-04-14]\n\n- Added `--quiet` flag to suppress any non-error output to stderr\n- Fixed a bug for the `--restrict-collaboration` flag for `box folders:update` where previously the flag would not restrict the collaborations when passed as true and would restrict collaborations when passed as false\n- Added `box trash:restore` to restore a trashed item and `box trash:get` to get information on a trashed item\n- Fixed a bug where flags that can be specified multiple times in a single command could not be passed through the command line for bulk commands\n- **Note**: Skipped version 2.5.0 due to development of new release process\n\n## [2.4.0](https://github.com/box/boxcli/compare/v2.3.0...v2.4.0) [2019-08-29]\n\n- Fixed an issue where the CSV formatting of commands that return multiple different object types (e.g\n  `box files:metadata:list` and `box search`) would only include the columns from the first object in the result set.\n  These commands now output the full set of columns across all objects in the result set.\n- Added a success message to `box collaborations:update` when setting `--role=owner`; previously the command would\n  output `undefined`.\n- Added support for setting external App User IDs in the `box users:create` and `box users:update` commands with\n  the `--external-id` flag\n\n## [2.3.0](https://github.com/box/boxcli/compare/v2.2.0...v2.3.0) [2019-05-23]\n\n- Added `--confirm` flag to the `box users:email-aliases:add` command to automatically confirm the email alias\n- Added `--restrict-to-enterprise` flag to the `box folders:update` command to restrict collaboration on the folder\n  to the owner's enterprise\n- Fixed a bug in the `box folders:update` command where the `--upload-email-access` flag would not correctly set\n  the folder upload email access level\n\n## [2.2.0](https://github.com/box/boxcli/compare/v2.1.0...v2.2.0) [2019-04-30]\n\n- Added `--sort` and `--direction` flags to `box search` to control the sort order of the search results\n- Fixed `box collections:add` to work correctly with `web_link` items\n- Fixed an issue where some commands including `box folders:collaborations:add` could incorrectly interpret bulk\n  input entries and produce unintended API requests\n- Added `box folders:metadata:set` and `box files:metadata:set` commands to apply metadata keys and values, overwriting\n  existing metadata under those keys\n- Errors encountered during bulk input are now caught within the CLI, skipping that entry and continuing bulk input.\n  The CLI should now run all bulk input entries to completion and report entries that produced errors after all entries\n  have been processed.\n\n## [2.1.0](https://github.com/box/boxcli/compare/v2.0.0...v2.1.0) [2019-03-28]\n\n- Fixed an issue where the `--fields` flag was not always requesting additional fields from the API\n- Fixed the `--event-types` flag for the `box events` and `box events:poll` commands\n- Updated to`lodash@4.17.11` to address a potential prototype pollution vulnerability\n- Fixed paging in both the `box events` and `box events:poll` commands:\n\t- The `box events` command now requires either a closed date range (defaults to last five days), or a stream\n\t  position.  If given a date range, all events in that range will be returned.  If given a stream position,\n\t  up to `limit` events will be returned along with the next stream position\n\t- `box events:poll` now correctly polls for new events\n\n## [2.0.0](https://github.com/box/boxcli/compare/v1.1.1...v2.0.0) [2018-12-13]\n\n### Features and Enhancements\n- __Full API parity:__ The new version of the CLI supports all available API endpoints and parameters\n- __Recursive folder upload and download:__ Uploading or downloading a folder now preserves the entire deep folder\n  structure\n- __Expanded human-readable output:__ All object fields returned by the API are now displayed by default, and can be\n  controlled with `--fields`.  All commands that output collections of objects no longer require interactive key presses\n  to view all objects.\n- __More output options for bulk commands:__ Bulk commands no longer require output to be written to disk, and can\n  output JSON, CSV, or human-readable output directly to stdout or to any file.\n- __More flexible date/time input:__ Date-times can now be specified in UNIX epoch format (e.g. `1535336043`), with a\n  year offset shorthand (e.g. `-1y` for \"one year ago\"), and as a combination of offset shorthands (e.g. `-5h30m` for\n  \"5 minutes and 30 seconds ago\")\n- __All commands now accept bulk input:__ Every command can now accept its arguments and flags from a file input in\n  either CSV or JSON format!  There is also no more need for CSV templates, since the column names are the same as the\n  CLI's own args and flags (case-insensitive).  Looking at the help for a command should tell you everything you need\n  to know to run the command in bulk\n- __All commands can now save output to disk:__ Every command now allows passing the `--save` and `--save-to-file-path`\n  flags to save the output to disk.  The output written will respect the `--json` and `--csv` flags for specifying\n  output format, otherwise it will use the file format in the CLI settings.\n- __Custom API calls:__ The new `box request` command allows making any API call against the Box API, and can be used\n  to pass arbitrary URLs and parameters\n- __Per-environment token caching enabled by default:__ To improve performance when running multiple commands, each\n  environment now caches the primary Service Account tokens by default.  This can be disabled by running\n  `box configure:environments:update --no-cache-tokens`\n- __Command correction and autocomplete:__ If you mis-type a command, you will now be prompted if there is an available\n  correction; selecting \"yes\" at the prompt will run the corrected command for you.  There is also now a\n  `box autocomplete` command, which will help you set up autocompletion (currently available only in bash and zsh\n  shells)\n- __User-friendly prompts:__ Some commands (e.g. `box configure:environments:select`) can now be called without\n  providing the necessary arguments; in this case, the command will display a helpful prompt to allow selecting the\n  argument value.\n- __Re-organized command hierarchy:__ We've renamed and reorganized many of the commands in the CLI to clarify the\n  inputs they take and reduce unnecessary subcommand nesting.  In some cases, this drastically reduces the length of\n  the command.  For example, `box files:shared-links:create` is now `box files:share` — 14 characters shorter!  Most\n  commands that were previously available as `xyzs:list` are now just `xyzs`; for example,\n  `box folders collaborations list` is now `box folders:collaborations`\n- __Download commands can download to a specified location on disk:__ Pass the `--destination` flag to have the files or\n  folders download to any location\n\n### ⚠ BREAKING CHANGES\n\n- The `box files:metadata:*`, `box folders:metadata:*`, and `box metadata-templates:*` command interfaces have changed;\n  please run the commands with `--help` for more details\n- All `box sessions` commands have been removed; use `box configure:environments:switch-user [USER_ID]` to switch\n  between users.\n- All `box configure settings` subcommands have been removed; these settings can be set by passing the appropriate\n  flag(s) to `box configure:settings`\n- `box files shared-links get [fileID]` is replaced by `box files:get [fileID] --fields=shared_link`\n  (output format differs)\n- `box folders shared-links get [folderID]` is replaced by `box folders:get [folderID] --fields=shared_link`\n  (output format differs)\n- `box folders change-upload-email [folderID] [access]` is replaced by\n  `box folders:update [folderID] --upload-email-access=[access]` (output format differs)\n- `box storage-policies assignments add [userID] [policyID]` is replaced by\n  `box storage-policies:assign [policyID] [userID]` (same functionality, may make more API calls)\n- `box storage-policies assignments update [assignmentID] [policyID]` is deprecated in favor of\n  `box storage-policies:assign [policyID] [userID]`\n- `box users change-primary-email [userID] [email]` is replaced by `box users:update [userID] --login=[email]`\n  (output format differs)\n- The `--list-members flag` has been removed from the `box groups:membership:list` command; this is now the default\n  behavior of the command and does not need to be specified via flag.\n- The `--list-groups` flag on `box groups:membership:list` has been removed; this functionality is now found in\n  the `box users:groups` command.\n- The `--list-collaborations` flag on `box groups:membership:list` has been removed; this functionality is now found\n  in the `box groups:collaborations` command.\n- Multi-word collaboration roles specified via the `-r|--role` flag in `box collaborations:add` and similar commands\n  are now separated by an underscore (e.g `viewer_uploader`) instead of a space.  This should make it easier to work\n  with these commands without needing to quote the flag value.\n- The `-y|--yes` flag has been removed from some commands; deletions of users, folders, files, etc will no longer\n  prompt to confirm that the item should be deleted.\n- The `-m|--multi` flag has been removed from `box files:download` and `box folders:download` since these commands\n  now accept bulk input via CSV.\n- The `--id-only` flag has been removed from `box folders:move`, since a folder move within a user's account should\n  not change the folder ID.\n- The `--parent-folder-id` flag has been removed from the `box folders:update` command; users should use\n  `box folders:move` instead.\n- The `--shared-link-*` flags have been removed from the `box folders:update` command; users should use\n  `box folders:share` instead.\n- The `--sync-disable` flag on `box users:create` and `box users:update` is now called `--no-sync-enable`\n- The `--is-exempt-from-device-limits` flag on `box users:create` and `box users:update` is now called\n  `--exempt-from-device-limits`\n- The `--not-exempt-from-device-limits` flag on `box users:create` and `box users:update` is now called\n  `--no-exempt-from-device-limits`\n- The `--is-exempt-login-verification` flag on `box users:create` and `box users:update` is now called\n  `--exempt-from-2fa`\n- The `--not-exempt-login-verification` flag on `box users:create` and `box users:update` is now called\n  `--no-exempt-from-2fa`\n- The `--parent-folder` flag on `box files:upload` is now called `--parent-id` for consistency with other commands\n- The `box storage-policies:assign` command no longer takes two arguments (a type and ID), and instead now takes\n  one argument (the ID) and has a `--type` flag with default value \"user\" to make the command easier to run for common\n  use cases\n- The `box webhooks:create` command no longer takes four arguments (target type, target ID, triggers, and URL), but\n  instead now takes two arguments (the target type and ID) and has two new flags: `--triggers` and `--address` to make\n  it easier to specify without needing to remember the argument order\n- The `--limit` flag on `box users:list` and `box collaborations:list-for-group` has been removed; all results will\n  be returned by default\n- The short code for the `box users:create --status` flag was changed from `-s` to `-S` to disambiguate from the\n  global `--save` flag\n- The short code for the `box webhooks:update --triggers` flag was changed from `-t` to `-T` to disambiguate from\n  the global `--token` flag\n- The bulk input file format for `box collaborations:add` has changed; see `--help` for more details\n\n### Bug Fixes\n- The `--json` flag in the search command works correctly now\n- Windows absolute paths without the drive letter (e.g. `\\MyFolder\\file.pdf`) now work correctly\n- Uploading files over 4 GB in size now works correctly\n- Listing the items in a folder with more than 300,000 items should no longer fail with an invalid offset error\n\n## [1.1.1](https://github.com/box/boxcli/compare/v1.1.0...v1.1.1)\n\n- Fixed bug preventing removal of a user from an Enterprise and conversion to a free user account.\n- Fixed bug that returned incorrect total count when using `box list users -m` to only list managed users.\n- Added CreatedAt field to CSV output for events.\n- Removed SyncState from CSV for creating folders.\n- Enabled setting a description for a folder when creating the folder.\n\n## [1.1.0](https://github.com/box/boxcli/compare/v1.0.2...v1.1.0)\n\n- Added new feature on all commands for using an individual token. Add the `--token` option to perform an individual command with the Box CLI using a specific token you provide. The feature is most useful when paired with the Developer Token you can generate through the Box Developer Console. When working with an application you create in the Box Developer Console, you will not need to authorize the application into a Box Enterprise before working with the Developer Token. For example usage: `box users get me --token <token_string>`. Certain commands may fail based on the permissions of the user to which the token you use belongs.\n- Fixed a bug preventing `previewer` being used when adding or updating a collaboration.\n- Added the following commands: `box collaborations delete`, `box folders collaborations delete`, `box files collaborations delete`.\n- Improved error messaging for failure on registering a configuration file and private key file with the Box CLI when creating a new CLI `environment`.\n- Added `--disable-file-path-translation` to the following commands: `box configure environments add`, `box configure environments update-config-file-path`, `box configure environments update-private-key-path`. This option ignores any additional processing on trying to resolve the file paths you provide when creating and updating Box CLI `environments`.\n- Fixed visual bug with upload progress tracker.\n- Updated Box .Net SDK to v3.3.0.\n- Changed Box CLI output to JSON by default with no existing `.box` directory.\n\n## [1.0.2](https://github.com/box/boxcli/compare/v1.0.1...v1.0.2)\n- Added shared link commands for Create, Get, Update, and Delete. Located as standalone commands under `box shared-links` as well as under `box folders shared-links` and `box files shared-links`.\n- Fixed UTF-8 issue obscuring characters when saving CSV reports.\n- Added autopaging for events and fixed faulty event Get command.\n- Added date options `w` for weeks and `now` when using date options with commands.\n\n## [1.0.1](https://github.com/box/boxcli/compare/v1.0.0...v1.0.1)\n\n- Fixed minor bug preventing --name, --description, and --etag options from working on the `box folders update` command\n- Added a `box folders rename` command.\n\n## [1.0.0](https://github.com/box/boxcli/compare/v1.0.0...v1.0.0)\n\n- Welcome to the Box CLI!\n"
  },
  {
    "path": "CONTRIBUTING.md",
    "content": "# Contributing\n\nAll contributions are welcome to this project.\n\n## Contributor License Agreement\n\nBefore a contribution can be merged into this project, please fill out the Contributor License Agreement (CLA) located at:\n\nhttp://opensource.box.com/cla\n\nTo learn more about CLAs and why they are important to open source projects, please see the [Wikipedia entry](http://en.wikipedia.org/wiki/Contributor_License_Agreement).\n\n## Code of Conduct\n\nThis project adheres to the [Box Open Code of Conduct](http://opensource.box.com/code-of-conduct/). By participating, you are expected to uphold this code.\n\n## How to contribute\n\n* **File an issue** - if you found a bug, want to request an enhancement, or want to implement something (bug fix or feature).\n* **Send a pull request** - if you want to contribute code. Please be sure to file an issue first.\n\n## Pull request best practices\n\nWe want to accept your pull requests. Please follow these steps:\n\n### Step 1: File an issue\n\nBefore writing any code, please file an issue stating the problem you want to solve or the feature you want to implement. This allows us to give you feedback before you spend any time writing code. There may be a known limitation that can't be addressed, or a bug that has already been fixed in a different way. The issue allows us to communicate and figure out if it's worth your time to write a bunch of code for the project.\n\n### Step 2: Fork this repository in GitHub\n\nThis will create your own copy of our repository.\n\n### Step 3: Add the upstream source\n\nThe upstream source is the project under the Box organization on GitHub. To add an upstream source for this project, type:\n\n```\ngit remote add upstream git@github.com:box/boxcli.git\n```\n\nThis will come in useful later.\n\n### Step 4: Create a feature branch\n\nCreate a branch with a descriptive name, such as `add-search`.\n\n### Step 5: Push your feature branch to your fork\n\nWe use [semantic-versioning](https://semver.org/) and the [conventional commit message format](https://www.conventionalcommits.org/en/v1.0.0/). Keep a separate feature branch for each issue you want to address. As you develop code, continue to push code to your remote feature branch. Example:\n\n```\ntag: short description\n\nlonger description here if necessary.\n```\n\nThe message summary should be a one-sentence description of the change, and it must be 72 characters in length or shorter. For a list of tags, please [click here](https://github.com/commitizen/conventional-commit-types/blob/master/index.json). Note that you must include the `!` for breaking changes (e.g. `feat!: removed old apis`).\n\nShown below are examples of the release type that will be done based on a commit message.\n\n#### Commit Types\n\n\"Semantic versioning\" means that changes to the version number of the package (e.g. `3.42.11` to `3.43.0`) are done according to rules that indicate how the change will affect consumers. Read more on the [semver page](https://semver.org/).\n\nThe version number is broken into 3 positions &mdash; `Major.Minor.Patch`. In semantic release terms, changes to the numbers follow `Breaking.Feature.Fix`. The `release` script parses commit messages and decides what type of release to make based on the types of commits detected since the last release.\n\nThe rules for commit types are:\n\n- Anything that changes or removes an API, option, or output format is a breaking change denoted by `!`.\n- Anything that adds new functionality in a backwards-compatible way is a feature (`feat`). Consumers have to upgrade to the new version to use the feature, but nothing will break if they do so.\n- Bugfixes (`fix`) for existing behavior are a patch. Consumers don't have to do anything but upgrade.\n- Other prefixes, such as `docs` or `chore`, don't trigger releases and don't appear in the changelog. These tags signal that there are **no external changes to _any_ APIs** (including non-breaking ones).\n\nIn most cases, commits will be a `feat` or `fix`. Make sure to include the `!` in the title if there are non-backwards-compatible changes in the commit.\n\n| Commit message                                                                                                                                          | Release type       | New version |\n| ------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------ | ----------- |\n| `feat!: remove old files endpoints`                                                                                                                     | Major (\"breaking\") | `X+1.0.0`   |\n| `feat: add new file upload endpoint`                                                                                                                    | Minor (\"feature\")  | `X.Y+1.0`   |\n| `fix: file streaming during download`                                                                                                                   | Patch (\"fix\")      | `X.Y.Z+1`   |\n| `docs: document files api`                                                                                                                              | No release         | `X.Y.Z`     |\n| `chore: remove commented code from file upload`                                                                                                         | No release         | `X.Y.Z`     |\n| `refactor: rename a variable (invisible change)`                                                                                                        | No release         | `X.Y.Z`     |\n\n### Step 6: Rebase\n\nBefore sending a pull request, rebase against upstream, such as:\n\n```\ngit fetch upstream\ngit rebase upstream/main\n```\n\nThis will add your changes on top of what's already in upstream, minimizing merge issues.\n\n### Step 7: Run the tests\n\nMake sure that all tests are passing before submitting a pull request.\n\n### Step 8: Send the pull request\n\nSend the pull request from your feature branch to us. Be sure to include a description that lets us know what work you did.\n\nKeep in mind that we like to see one issue addressed per pull request, as this helps keep our git history clean and we can more easily track down issues.\n"
  },
  {
    "path": "LICENSE",
    "content": "                             Apache License\n                       Version 2.0, January 2004\n                    http://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n  \"License\" shall mean the terms and conditions for use, reproduction,\n  and distribution as defined by Sections 1 through 9 of this document.\n  \"Licensor\" shall mean the copyright owner or entity authorized by\n  the copyright owner that is granting the License.\n  \"Legal Entity\" shall mean the union of the acting entity and all\n  other entities that control, are controlled by, or are under common\n  control with that entity. For the purposes of this definition,\n  \"control\" means (i) the power, direct or indirect, to cause the\n  direction or management of such entity, whether by contract or\n  otherwise, or (ii) ownership of fifty percent (50%) or more of the\n  outstanding shares, or (iii) beneficial ownership of such entity.\n  \"You\" (or \"Your\") shall mean an individual or Legal Entity\n  exercising permissions granted by this License.\n  \"Source\" form shall mean the preferred form for making modifications,\n  including but not limited to software source code, documentation\n  source, and configuration files.\n  \"Object\" form shall mean any form resulting from mechanical\n  transformation or translation of a Source form, including but\n  not limited to compiled object code, generated documentation,\n  and conversions to other media types.\n  \"Work\" shall mean the work of authorship, whether in Source or\n  Object form, made available under the License, as indicated by a\n  copyright notice that is included in or attached to the work\n  (an example is provided in the Appendix below).\n  \"Derivative Works\" shall mean any work, whether in Source or Object\n  form, that is based on (or derived from) the Work and for which the\n  editorial revisions, annotations, elaborations, or other modifications\n  represent, as a whole, an original work of authorship. For the purposes\n  of this License, Derivative Works shall not include works that remain\n  separable from, or merely link (or bind by name) to the interfaces of,\n  the Work and Derivative Works thereof.\n  \"Contribution\" shall mean any work of authorship, including\n  the original version of the Work and any modifications or additions\n  to that Work or Derivative Works thereof, that is intentionally\n  submitted to Licensor for inclusion in the Work by the copyright owner\n  or by an individual or Legal Entity authorized to submit on behalf of\n  the copyright owner. For the purposes of this definition, \"submitted\"\n  means any form of electronic, verbal, or written communication sent\n  to the Licensor or its representatives, including but not limited to\n  communication on electronic mailing lists, source code control systems,\n  and issue tracking systems that are managed by, or on behalf of, the\n  Licensor for the purpose of discussing and improving the Work, but\n  excluding communication that is conspicuously marked or otherwise\n  designated in writing by the copyright owner as \"Not a Contribution.\"\n  \"Contributor\" shall mean Licensor and any individual or Legal Entity\n  on behalf of whom a Contribution has been received by Licensor and\n  subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n  this License, each Contributor hereby grants to You a perpetual,\n  worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n  copyright license to reproduce, prepare Derivative Works of,\n  publicly display, publicly perform, sublicense, and distribute the\n  Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n  this License, each Contributor hereby grants to You a perpetual,\n  worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n  (except as stated in this section) patent license to make, have made,\n  use, offer to sell, sell, import, and otherwise transfer the Work,\n  where such license applies only to those patent claims licensable\n  by such Contributor that are necessarily infringed by their\n  Contribution(s) alone or by combination of their Contribution(s)\n  with the Work to which such Contribution(s) was submitted. If You\n  institute patent litigation against any entity (including a\n  cross-claim or counterclaim in a lawsuit) alleging that the Work\n  or a Contribution incorporated within the Work constitutes direct\n  or contributory patent infringement, then any patent licenses\n  granted to You under this License for that Work shall terminate\n  as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n  Work or Derivative Works thereof in any medium, with or without\n  modifications, and in Source or Object form, provided that You\n  meet the following conditions:\n\n  (a) You must give any other recipients of the Work or\n      Derivative Works a copy of this License; and\n\n  (b) You must cause any modified files to carry prominent notices\n      stating that You changed the files; and\n\n  (c) You must retain, in the Source form of any Derivative Works\n      that You distribute, all copyright, patent, trademark, and\n      attribution notices from the Source form of the Work,\n      excluding those notices that do not pertain to any part of\n      the Derivative Works; and\n\n  (d) If the Work includes a \"NOTICE\" text file as part of its\n      distribution, then any Derivative Works that You distribute must\n      include a readable copy of the attribution notices contained\n      within such NOTICE file, excluding those notices that do not\n      pertain to any part of the Derivative Works, in at least one\n      of the following places: within a NOTICE text file distributed\n      as part of the Derivative Works; within the Source form or\n      documentation, if provided along with the Derivative Works; or,\n      within a display generated by the Derivative Works, if and\n      wherever such third-party notices normally appear. The contents\n      of the NOTICE file are for informational purposes only and\n      do not modify the License. You may add Your own attribution\n      notices within Derivative Works that You distribute, alongside\n      or as an addendum to the NOTICE text from the Work, provided\n      that such additional attribution notices cannot be construed\n      as modifying the License.\n\n  You may add Your own copyright statement to Your modifications and\n  may provide additional or different license terms and conditions\n  for use, reproduction, or distribution of Your modifications, or\n  for any such Derivative Works as a whole, provided Your use,\n  reproduction, and distribution of the Work otherwise complies with\n  the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n  any Contribution intentionally submitted for inclusion in the Work\n  by You to the Licensor shall be under the terms and conditions of\n  this License, without any additional terms or conditions.\n  Notwithstanding the above, nothing herein shall supersede or modify\n  the terms of any separate license agreement you may have executed\n  with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n  names, trademarks, service marks, or product names of the Licensor,\n  except as required for reasonable and customary use in describing the\n  origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n  agreed to in writing, Licensor provides the Work (and each\n  Contributor provides its Contributions) on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n  implied, including, without limitation, any warranties or conditions\n  of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n  PARTICULAR PURPOSE. You are solely responsible for determining the\n  appropriateness of using or redistributing the Work and assume any\n  risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n  whether in tort (including negligence), contract, or otherwise,\n  unless required by applicable law (such as deliberate and grossly\n  negligent acts) or agreed to in writing, shall any Contributor be\n  liable to You for damages, including any direct, indirect, special,\n  incidental, or consequential damages of any character arising as a\n  result of this License or out of the use or inability to use the\n  Work (including but not limited to damages for loss of goodwill,\n  work stoppage, computer failure or malfunction, or any and all\n  other commercial damages or losses), even if such Contributor\n  has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n  the Work or Derivative Works thereof, You may choose to offer,\n  and charge a fee for, acceptance of support, warranty, indemnity,\n  or other liability obligations and/or rights consistent with this\n  License. However, in accepting such obligations, You may act only\n  on Your own behalf and on Your sole responsibility, not on behalf\n  of any other Contributor, and only if You agree to indemnify,\n  defend, and hold each Contributor harmless for any liability\n  incurred by, or claims asserted against, such Contributor by reason\n  of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n"
  },
  {
    "path": "LICENSE-THIRD-PARTY.txt",
    "content": "This file was generated with the generate-license-file npm package!\nhttps://www.npmjs.com/package/generate-license-file\n\nThe following npm package may be included in this product:\n\n - ejs@3.1.10\n\nThis package contains the following license:\n\nApache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"[]\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright [yyyy] [name of copyright owner]\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - parseurl@1.3.3\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2014 Jonathan Ong <me@jongleberry.com>\nCopyright (c) 2014-2017 Douglas Christopher Wilson <doug@somethingdoug.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - source-map@0.6.1\n\nThis package contains the following license:\n\nCopyright (c) 2009-2011, Mozilla Foundation and contributors\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the names of the Mozilla Foundation nor the names of project\n  contributors may be used to endorse or promote products derived from this\n  software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - statuses@2.0.1\n - statuses@2.0.2\n\nThese packages each contain the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Jonathan Ong <me@jongleberry.com>\nCopyright (c) 2016 Douglas Christopher Wilson <doug@somethingdoug.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - ee-first@1.1.1\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Jonathan Ong me@jongleberry.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - destroy@1.2.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Jonathan Ong me@jongleberry.com\nCopyright (c) 2015-2022 Douglas Christopher Wilson doug@somethingdoug.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - http-errors@2.0.0\n - http-errors@2.0.1\n\nThese packages each contain the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Jonathan Ong me@jongleberry.com\nCopyright (c) 2016 Douglas Christopher Wilson doug@somethingdoug.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - detect-libc@2.1.2\n\nThis package contains the following license:\n\nApache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright {yyyy} {name of copyright owner}\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - before-after-hook@4.0.0\n\nThis package contains the following license:\n\nApache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2018 Gregor Martynus and other contributors.\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - rxjs@7.8.2\n\nThis package contains the following license:\n\nApache License\n                         Version 2.0, January 2004\n                      http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n    \"License\" shall mean the terms and conditions for use, reproduction,\n    and distribution as defined by Sections 1 through 9 of this document.\n\n    \"Licensor\" shall mean the copyright owner or entity authorized by\n    the copyright owner that is granting the License.\n\n    \"Legal Entity\" shall mean the union of the acting entity and all\n    other entities that control, are controlled by, or are under common\n    control with that entity. For the purposes of this definition,\n    \"control\" means (i) the power, direct or indirect, to cause the\n    direction or management of such entity, whether by contract or\n    otherwise, or (ii) ownership of fifty percent (50%) or more of the\n    outstanding shares, or (iii) beneficial ownership of such entity.\n\n    \"You\" (or \"Your\") shall mean an individual or Legal Entity\n    exercising permissions granted by this License.\n\n    \"Source\" form shall mean the preferred form for making modifications,\n    including but not limited to software source code, documentation\n    source, and configuration files.\n\n    \"Object\" form shall mean any form resulting from mechanical\n    transformation or translation of a Source form, including but\n    not limited to compiled object code, generated documentation,\n    and conversions to other media types.\n\n    \"Work\" shall mean the work of authorship, whether in Source or\n    Object form, made available under the License, as indicated by a\n    copyright notice that is included in or attached to the work\n    (an example is provided in the Appendix below).\n\n    \"Derivative Works\" shall mean any work, whether in Source or Object\n    form, that is based on (or derived from) the Work and for which the\n    editorial revisions, annotations, elaborations, or other modifications\n    represent, as a whole, an original work of authorship. For the purposes\n    of this License, Derivative Works shall not include works that remain\n    separable from, or merely link (or bind by name) to the interfaces of,\n    the Work and Derivative Works thereof.\n\n    \"Contribution\" shall mean any work of authorship, including\n    the original version of the Work and any modifications or additions\n    to that Work or Derivative Works thereof, that is intentionally\n    submitted to Licensor for inclusion in the Work by the copyright owner\n    or by an individual or Legal Entity authorized to submit on behalf of\n    the copyright owner. For the purposes of this definition, \"submitted\"\n    means any form of electronic, verbal, or written communication sent\n    to the Licensor or its representatives, including but not limited to\n    communication on electronic mailing lists, source code control systems,\n    and issue tracking systems that are managed by, or on behalf of, the\n    Licensor for the purpose of discussing and improving the Work, but\n    excluding communication that is conspicuously marked or otherwise\n    designated in writing by the copyright owner as \"Not a Contribution.\"\n\n    \"Contributor\" shall mean Licensor and any individual or Legal Entity\n    on behalf of whom a Contribution has been received by Licensor and\n    subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n    this License, each Contributor hereby grants to You a perpetual,\n    worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n    copyright license to reproduce, prepare Derivative Works of,\n    publicly display, publicly perform, sublicense, and distribute the\n    Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n    this License, each Contributor hereby grants to You a perpetual,\n    worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n    (except as stated in this section) patent license to make, have made,\n    use, offer to sell, sell, import, and otherwise transfer the Work,\n    where such license applies only to those patent claims licensable\n    by such Contributor that are necessarily infringed by their\n    Contribution(s) alone or by combination of their Contribution(s)\n    with the Work to which such Contribution(s) was submitted. If You\n    institute patent litigation against any entity (including a\n    cross-claim or counterclaim in a lawsuit) alleging that the Work\n    or a Contribution incorporated within the Work constitutes direct\n    or contributory patent infringement, then any patent licenses\n    granted to You under this License for that Work shall terminate\n    as of the date such litigation is filed.\n\n 4. Redistribution. You may reproduce and distribute copies of the\n    Work or Derivative Works thereof in any medium, with or without\n    modifications, and in Source or Object form, provided that You\n    meet the following conditions:\n\n    (a) You must give any other recipients of the Work or\n        Derivative Works a copy of this License; and\n\n    (b) You must cause any modified files to carry prominent notices\n        stating that You changed the files; and\n\n    (c) You must retain, in the Source form of any Derivative Works\n        that You distribute, all copyright, patent, trademark, and\n        attribution notices from the Source form of the Work,\n        excluding those notices that do not pertain to any part of\n        the Derivative Works; and\n\n    (d) If the Work includes a \"NOTICE\" text file as part of its\n        distribution, then any Derivative Works that You distribute must\n        include a readable copy of the attribution notices contained\n        within such NOTICE file, excluding those notices that do not\n        pertain to any part of the Derivative Works, in at least one\n        of the following places: within a NOTICE text file distributed\n        as part of the Derivative Works; within the Source form or\n        documentation, if provided along with the Derivative Works; or,\n        within a display generated by the Derivative Works, if and\n        wherever such third-party notices normally appear. The contents\n        of the NOTICE file are for informational purposes only and\n        do not modify the License. You may add Your own attribution\n        notices within Derivative Works that You distribute, alongside\n        or as an addendum to the NOTICE text from the Work, provided\n        that such additional attribution notices cannot be construed\n        as modifying the License.\n\n    You may add Your own copyright statement to Your modifications and\n    may provide additional or different license terms and conditions\n    for use, reproduction, or distribution of Your modifications, or\n    for any such Derivative Works as a whole, provided Your use,\n    reproduction, and distribution of the Work otherwise complies with\n    the conditions stated in this License.\n\n 5. Submission of Contributions. Unless You explicitly state otherwise,\n    any Contribution intentionally submitted for inclusion in the Work\n    by You to the Licensor shall be under the terms and conditions of\n    this License, without any additional terms or conditions.\n    Notwithstanding the above, nothing herein shall supersede or modify\n    the terms of any separate license agreement you may have executed\n    with Licensor regarding such Contributions.\n\n 6. Trademarks. This License does not grant permission to use the trade\n    names, trademarks, service marks, or product names of the Licensor,\n    except as required for reasonable and customary use in describing the\n    origin of the Work and reproducing the content of the NOTICE file.\n\n 7. Disclaimer of Warranty. Unless required by applicable law or\n    agreed to in writing, Licensor provides the Work (and each\n    Contributor provides its Contributions) on an \"AS IS\" BASIS,\n    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n    implied, including, without limitation, any warranties or conditions\n    of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n    PARTICULAR PURPOSE. You are solely responsible for determining the\n    appropriateness of using or redistributing the Work and assume any\n    risks associated with Your exercise of permissions under this License.\n\n 8. Limitation of Liability. In no event and under no legal theory,\n    whether in tort (including negligence), contract, or otherwise,\n    unless required by applicable law (such as deliberate and grossly\n    negligent acts) or agreed to in writing, shall any Contributor be\n    liable to You for damages, including any direct, indirect, special,\n    incidental, or consequential damages of any character arising as a\n    result of this License or out of the use or inability to use the\n    Work (including but not limited to damages for loss of goodwill,\n    work stoppage, computer failure or malfunction, or any and all\n    other commercial damages or losses), even if such Contributor\n    has been advised of the possibility of such damages.\n\n 9. Accepting Warranty or Additional Liability. While redistributing\n    the Work or Derivative Works thereof, You may choose to offer,\n    and charge a fee for, acceptance of support, warranty, indemnity,\n    or other liability obligations and/or rights consistent with this\n    License. However, in accepting such obligations, You may act only\n    on Your own behalf and on Your sole responsibility, not on behalf\n    of any other Contributor, and only if You agree to indemnify,\n    defend, and hold each Contributor harmless for any liability\n    incurred by, or claims asserted against, such Contributor by reason\n    of your accepting any such warranty or additional liability.\n\n END OF TERMS AND CONDITIONS\n\n APPENDIX: How to apply the Apache License to your work.\n\n    To apply the Apache License to your work, attach the following\n    boilerplate notice, with the fields enclosed by brackets \"[]\"\n    replaced with your own identifying information. (Don't include\n    the brackets!)  The text should be enclosed in the appropriate\n    comment syntax for the file format. We also recommend that a\n    file or class name and description of purpose be included on the\n    same \"printed page\" as the copyright notice for easier\n    identification within third-party archives.\n\n Copyright (c) 2015-2018 Google, Inc., Netflix, Inc., Microsoft Corp. and contributors\n\n Licensed under the Apache License, Version 2.0 (the \"License\");\n you may not use this file except in compliance with the License.\n You may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\n Unless required by applicable law or agreed to in writing, software\n distributed under the License is distributed on an \"AS IS\" BASIS,\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n See the License for the specific language governing permissions and\n limitations under the License.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - box-node-sdk@4.3.0\n\nThis package contains the following license:\n\nApache License\n                       Version 2.0, January 2004\n                    http://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n  \"License\" shall mean the terms and conditions for use, reproduction,\n  and distribution as defined by Sections 1 through 9 of this document.\n  \"Licensor\" shall mean the copyright owner or entity authorized by\n  the copyright owner that is granting the License.\n  \"Legal Entity\" shall mean the union of the acting entity and all\n  other entities that control, are controlled by, or are under common\n  control with that entity. For the purposes of this definition,\n  \"control\" means (i) the power, direct or indirect, to cause the\n  direction or management of such entity, whether by contract or\n  otherwise, or (ii) ownership of fifty percent (50%) or more of the\n  outstanding shares, or (iii) beneficial ownership of such entity.\n  \"You\" (or \"Your\") shall mean an individual or Legal Entity\n  exercising permissions granted by this License.\n  \"Source\" form shall mean the preferred form for making modifications,\n  including but not limited to software source code, documentation\n  source, and configuration files.\n  \"Object\" form shall mean any form resulting from mechanical\n  transformation or translation of a Source form, including but\n  not limited to compiled object code, generated documentation,\n  and conversions to other media types.\n  \"Work\" shall mean the work of authorship, whether in Source or\n  Object form, made available under the License, as indicated by a\n  copyright notice that is included in or attached to the work\n  (an example is provided in the Appendix below).\n  \"Derivative Works\" shall mean any work, whether in Source or Object\n  form, that is based on (or derived from) the Work and for which the\n  editorial revisions, annotations, elaborations, or other modifications\n  represent, as a whole, an original work of authorship. For the purposes\n  of this License, Derivative Works shall not include works that remain\n  separable from, or merely link (or bind by name) to the interfaces of,\n  the Work and Derivative Works thereof.\n  \"Contribution\" shall mean any work of authorship, including\n  the original version of the Work and any modifications or additions\n  to that Work or Derivative Works thereof, that is intentionally\n  submitted to Licensor for inclusion in the Work by the copyright owner\n  or by an individual or Legal Entity authorized to submit on behalf of\n  the copyright owner. For the purposes of this definition, \"submitted\"\n  means any form of electronic, verbal, or written communication sent\n  to the Licensor or its representatives, including but not limited to\n  communication on electronic mailing lists, source code control systems,\n  and issue tracking systems that are managed by, or on behalf of, the\n  Licensor for the purpose of discussing and improving the Work, but\n  excluding communication that is conspicuously marked or otherwise\n  designated in writing by the copyright owner as \"Not a Contribution.\"\n  \"Contributor\" shall mean Licensor and any individual or Legal Entity\n  on behalf of whom a Contribution has been received by Licensor and\n  subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of\n  this License, each Contributor hereby grants to You a perpetual,\n  worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n  copyright license to reproduce, prepare Derivative Works of,\n  publicly display, publicly perform, sublicense, and distribute the\n  Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of\n  this License, each Contributor hereby grants to You a perpetual,\n  worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n  (except as stated in this section) patent license to make, have made,\n  use, offer to sell, sell, import, and otherwise transfer the Work,\n  where such license applies only to those patent claims licensable\n  by such Contributor that are necessarily infringed by their\n  Contribution(s) alone or by combination of their Contribution(s)\n  with the Work to which such Contribution(s) was submitted. If You\n  institute patent litigation against any entity (including a\n  cross-claim or counterclaim in a lawsuit) alleging that the Work\n  or a Contribution incorporated within the Work constitutes direct\n  or contributory patent infringement, then any patent licenses\n  granted to You under this License for that Work shall terminate\n  as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the\n  Work or Derivative Works thereof in any medium, with or without\n  modifications, and in Source or Object form, provided that You\n  meet the following conditions:\n\n  (a) You must give any other recipients of the Work or\n      Derivative Works a copy of this License; and\n\n  (b) You must cause any modified files to carry prominent notices\n      stating that You changed the files; and\n\n  (c) You must retain, in the Source form of any Derivative Works\n      that You distribute, all copyright, patent, trademark, and\n      attribution notices from the Source form of the Work,\n      excluding those notices that do not pertain to any part of\n      the Derivative Works; and\n\n  (d) If the Work includes a \"NOTICE\" text file as part of its\n      distribution, then any Derivative Works that You distribute must\n      include a readable copy of the attribution notices contained\n      within such NOTICE file, excluding those notices that do not\n      pertain to any part of the Derivative Works, in at least one\n      of the following places: within a NOTICE text file distributed\n      as part of the Derivative Works; within the Source form or\n      documentation, if provided along with the Derivative Works; or,\n      within a display generated by the Derivative Works, if and\n      wherever such third-party notices normally appear. The contents\n      of the NOTICE file are for informational purposes only and\n      do not modify the License. You may add Your own attribution\n      notices within Derivative Works that You distribute, alongside\n      or as an addendum to the NOTICE text from the Work, provided\n      that such additional attribution notices cannot be construed\n      as modifying the License.\n\n  You may add Your own copyright statement to Your modifications and\n  may provide additional or different license terms and conditions\n  for use, reproduction, or distribution of Your modifications, or\n  for any such Derivative Works as a whole, provided Your use,\n  reproduction, and distribution of the Work otherwise complies with\n  the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise,\n  any Contribution intentionally submitted for inclusion in the Work\n  by You to the Licensor shall be under the terms and conditions of\n  this License, without any additional terms or conditions.\n  Notwithstanding the above, nothing herein shall supersede or modify\n  the terms of any separate license agreement you may have executed\n  with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade\n  names, trademarks, service marks, or product names of the Licensor,\n  except as required for reasonable and customary use in describing the\n  origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or\n  agreed to in writing, Licensor provides the Work (and each\n  Contributor provides its Contributions) on an \"AS IS\" BASIS,\n  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n  implied, including, without limitation, any warranties or conditions\n  of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n  PARTICULAR PURPOSE. You are solely responsible for determining the\n  appropriateness of using or redistributing the Work and assume any\n  risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory,\n  whether in tort (including negligence), contract, or otherwise,\n  unless required by applicable law (such as deliberate and grossly\n  negligent acts) or agreed to in writing, shall any Contributor be\n  liable to You for damages, including any direct, indirect, special,\n  incidental, or consequential damages of any character arising as a\n  result of this License or out of the use or inability to use the\n  Work (including but not limited to damages for loss of goodwill,\n  work stoppage, computer failure or malfunction, or any and all\n  other commercial damages or losses), even if such Contributor\n  has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing\n  the Work or Derivative Works thereof, You may choose to offer,\n  and charge a fee for, acceptance of support, warranty, indemnity,\n  or other liability obligations and/or rights consistent with this\n  License. However, in accepting such obligations, You may act only\n  on Your own behalf and on Your sole responsibility, not on behalf\n  of any other Contributor, and only if You agree to indemnify,\n  defend, and hold each Contributor harmless for any liability\n  incurred by, or claims asserted against, such Contributor by reason\n  of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - @types/bluebird@3.5.42\n - @types/cli-progress@3.11.6\n - @types/prop-types@15.7.15\n\nThese packages each contain the following license:\n\nMIT License\n\n    Copyright (c) Microsoft Corporation.\n\n    Permission is hereby granted, free of charge, to any person obtaining a copy\n    of this software and associated documentation files (the \"Software\"), to deal\n    in the Software without restriction, including without limitation the rights\n    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n    copies of the Software, and to permit persons to whom the Software is\n    furnished to do so, subject to the following conditions:\n\n    The above copyright notice and this permission notice shall be included in all\n    copies or substantial portions of the Software.\n\n    THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n    SOFTWARE\n\n-----------\n\nThe following npm package may be included in this product:\n\n - fast-levenshtein@3.0.0\n\nThis package contains the following license:\n\n(MIT License)\n\nCopyright (c) 2013 [Ramesh Nair](http://www.hiddentao.com/)\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - balanced-match@1.0.2\n\nThis package contains the following license:\n\n(MIT)\n\nCopyright (c) 2013 Julian Gruber &lt;julian@juliangruber.com&gt;\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - express@4.22.1\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2009-2014 TJ Holowaychuk <tj@vision-media.ca>\nCopyright (c) 2013-2014 Roman Shtylman <shtylman+expressjs@gmail.com>\nCopyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - serve-static@1.16.2\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2010 Sencha Inc.\nCopyright (c) 2011 LearnBoost\nCopyright (c) 2011 TJ Holowaychuk\nCopyright (c) 2014-2016 Douglas Christopher Wilson\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - js-yaml@3.14.2\n - js-yaml@4.1.1\n\nThese packages each contain the following license:\n\n(The MIT License)\n\nCopyright (C) 2011-2015 by Vitaly Puzrin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - fs-extra@10.1.0\n - fs-extra@9.1.0\n\nThese packages each contain the following license:\n\n(The MIT License)\n\nCopyright (c) 2011-2017 JP Richardson\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files\n(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,\n merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\nWARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS\nOR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - argparse@1.0.10\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (C) 2012 by Vitaly Puzrin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - send@0.19.0\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk\nCopyright (c) 2014-2022 Douglas Christopher Wilson\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - fresh@0.5.2\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2012 TJ Holowaychuk <tj@vision-media.ca>\nCopyright (c) 2016-2017 Douglas Christopher Wilson <doug@somethingdoug.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - escape-html@1.0.3\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2012-2013 TJ Holowaychuk\nCopyright (c) 2015 Andreas Lubbe\nCopyright (c) 2015 Tiancheng \"Timothy\" Gu\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - negotiator@0.6.3\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2012-2014 Federico Romero\nCopyright (c) 2012-2014 Isaac Z. Schlueter\nCopyright (c) 2014-2015 Douglas Christopher Wilson\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - cookie@0.7.1\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2012-2014 Roman Shtylman <shtylman@gmail.com>\nCopyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - bytes@3.1.2\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2012-2014 TJ Holowaychuk <tj@vision-media.ca>\nCopyright (c) 2015 Jed Watson <jed.watson@me.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - range-parser@1.2.1\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2012-2014 TJ Holowaychuk <tj@vision-media.ca>\nCopyright (c) 2015-2016 Douglas Christopher Wilson <doug@somethingdoug.com\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - jsonfile@6.2.0\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2012-2015, JP Richardson <jprichardson@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files\n(the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify,\n merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE\nWARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS\nOR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\n ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - on-finished@2.4.1\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2013 Jonathan Ong <me@jongleberry.com>\nCopyright (c) 2014 Douglas Christopher Wilson <doug@somethingdoug.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - merge-descriptors@1.0.3\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2013 Jonathan Ong <me@jongleberry.com>\nCopyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - promise-queue@2.2.5\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2013 Mikhail Davydov and other contributors\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - agent-base@7.1.4\n - https-proxy-agent@7.0.6\n - pac-resolver@7.0.1\n - proxy-agent@6.5.0\n - socks-proxy-agent@8.0.5\n\nThese packages each contain the following license:\n\n(The MIT License)\n\nCopyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - http-proxy-agent@7.0.2\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2013 Nathan Rajlich <nathan@tootallnate.net>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - methods@1.1.2\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2013-2014 TJ Holowaychuk <tj@vision-media.ca>\nCopyright (c) 2015-2016 Douglas Christopher Wilson <doug@somethingdoug.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - media-typer@0.3.0\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2014 Douglas Christopher Wilson\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - body-parser@1.20.4\n - type-is@1.6.18\n\nThese packages each contain the following license:\n\n(The MIT License)\n\nCopyright (c) 2014 Jonathan Ong <me@jongleberry.com>\nCopyright (c) 2014-2015 Douglas Christopher Wilson <doug@somethingdoug.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - accepts@1.3.8\n - mime-types@2.1.35\n\nThese packages each contain the following license:\n\n(The MIT License)\n\nCopyright (c) 2014 Jonathan Ong <me@jongleberry.com>\nCopyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - mime-db@1.52.0\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2014 Jonathan Ong <me@jongleberry.com>\nCopyright (c) 2015-2022 Douglas Christopher Wilson <doug@somethingdoug.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - util-deprecate@1.0.2\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - data-uri-to-buffer@6.0.2\n - get-uri@6.0.5\n\nThese packages each contain the following license:\n\n(The MIT License)\n\nCopyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - pac-proxy-agent@7.2.0\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2014 Nathan Rajlich <nathan@tootallnate.net>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - debug@2.6.9\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2014 TJ Holowaychuk <tj@vision-media.ca>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software \nand associated documentation files (the 'Software'), to deal in the Software without restriction, \nincluding without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, \nand/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial \nportions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT \nLIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. \nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, \nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE \nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - etag@1.8.1\n - proxy-addr@2.0.7\n\nThese packages each contain the following license:\n\n(The MIT License)\n\nCopyright (c) 2014-2016 Douglas Christopher Wilson\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - content-disposition@0.5.4\n - forwarded@0.2.0\n - vary@1.1.2\n\nThese packages each contain the following license:\n\n(The MIT License)\n\nCopyright (c) 2014-2017 Douglas Christopher Wilson\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - debug@4.4.3\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2014-2017 TJ Holowaychuk <tj@vision-media.ca>\nCopyright (c) 2018-2021 Josh Junon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software\nand associated documentation files (the 'Software'), to deal in the Software without restriction,\nincluding without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,\nand/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial\nportions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT\nLIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - depd@2.0.0\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2014-2018 Douglas Christopher Wilson\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - finalhandler@1.3.1\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2014-2022 Douglas Christopher Wilson <doug@somethingdoug.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - content-type@1.0.5\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2015 Douglas Christopher Wilson\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - unpipe@1.0.0\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2015 Douglas Christopher Wilson <doug@somethingdoug.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - encodeurl@1.0.2\n - encodeurl@2.0.0\n\nThese packages each contain the following license:\n\n(The MIT License)\n\nCopyright (c) 2016 Douglas Christopher Wilson\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n'Software'), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - universalify@2.0.1\n\nThis package contains the following license:\n\n(The MIT License)\n\nCopyright (c) 2017, Ryan Zimmerman <opensrc@ryanzim.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the 'Software'), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - universal-user-agent@7.0.3\n\nThis package contains the following license:\n\n# [ISC License](https://spdx.org/licenses/ISC)\n\nCopyright (c) 2018-2021, Gregor Martynus (https://github.com/gr2m)\n\nPermission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - process-nextick-args@2.0.1\n\nThis package contains the following license:\n\n# Copyright (c) 2015 Calvin Metcalf\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\n**THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.**\n\n-----------\n\nThe following npm package may be included in this product:\n\n - date-fns@1.30.1\n\nThis package contains the following license:\n\n# License\n\ndate-fns is licensed under the [MIT license](http://kossnocorp.mit-license.org).\nRead more about MIT at [TLDRLegal](https://tldrlegal.com/license/mit-license).\n\n-----------\n\nThe following npm package may be included in this product:\n\n - webidl-conversions@3.0.1\n\nThis package contains the following license:\n\n# The BSD 2-Clause License\n\nCopyright (c) 2014, Domenic Denicola\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - dashdash@1.14.1\n\nThis package contains the following license:\n\n# This is the MIT license\n\nCopyright (c) 2013 Trent Mick. All rights reserved.\nCopyright (c) 2013 Joyent Inc. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a\ncopy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be included\nin all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS\nOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - password-prompt@1.1.3\n\nThis package contains the following license:\n\n0BSD\n\n-----------\n\nThe following npm package may be included in this product:\n\n - argparse@2.0.1\n\nThis package contains the following license:\n\nA. HISTORY OF THE SOFTWARE\n==========================\n\nPython was created in the early 1990s by Guido van Rossum at Stichting\nMathematisch Centrum (CWI, see http://www.cwi.nl) in the Netherlands\nas a successor of a language called ABC.  Guido remains Python's\nprincipal author, although it includes many contributions from others.\n\nIn 1995, Guido continued his work on Python at the Corporation for\nNational Research Initiatives (CNRI, see http://www.cnri.reston.va.us)\nin Reston, Virginia where he released several versions of the\nsoftware.\n\nIn May 2000, Guido and the Python core development team moved to\nBeOpen.com to form the BeOpen PythonLabs team.  In October of the same\nyear, the PythonLabs team moved to Digital Creations, which became\nZope Corporation.  In 2001, the Python Software Foundation (PSF, see\nhttps://www.python.org/psf/) was formed, a non-profit organization\ncreated specifically to own Python-related Intellectual Property.\nZope Corporation was a sponsoring member of the PSF.\n\nAll Python releases are Open Source (see http://www.opensource.org for\nthe Open Source Definition).  Historically, most, but not all, Python\nreleases have also been GPL-compatible; the table below summarizes\nthe various releases.\n\n    Release         Derived     Year        Owner       GPL-\n                    from                                compatible? (1)\n\n    0.9.0 thru 1.2              1991-1995   CWI         yes\n    1.3 thru 1.5.2  1.2         1995-1999   CNRI        yes\n    1.6             1.5.2       2000        CNRI        no\n    2.0             1.6         2000        BeOpen.com  no\n    1.6.1           1.6         2001        CNRI        yes (2)\n    2.1             2.0+1.6.1   2001        PSF         no\n    2.0.1           2.0+1.6.1   2001        PSF         yes\n    2.1.1           2.1+2.0.1   2001        PSF         yes\n    2.1.2           2.1.1       2002        PSF         yes\n    2.1.3           2.1.2       2002        PSF         yes\n    2.2 and above   2.1.1       2001-now    PSF         yes\n\nFootnotes:\n\n(1) GPL-compatible doesn't mean that we're distributing Python under\n    the GPL.  All Python licenses, unlike the GPL, let you distribute\n    a modified version without making your changes open source.  The\n    GPL-compatible licenses make it possible to combine Python with\n    other software that is released under the GPL; the others don't.\n\n(2) According to Richard Stallman, 1.6.1 is not GPL-compatible,\n    because its license has a choice of law clause.  According to\n    CNRI, however, Stallman's lawyer has told CNRI's lawyer that 1.6.1\n    is \"not incompatible\" with the GPL.\n\nThanks to the many outside volunteers who have worked under Guido's\ndirection to make these releases possible.\n\n\nB. TERMS AND CONDITIONS FOR ACCESSING OR OTHERWISE USING PYTHON\n===============================================================\n\nPYTHON SOFTWARE FOUNDATION LICENSE VERSION 2\n--------------------------------------------\n\n1. This LICENSE AGREEMENT is between the Python Software Foundation\n(\"PSF\"), and the Individual or Organization (\"Licensee\") accessing and\notherwise using this software (\"Python\") in source or binary form and\nits associated documentation.\n\n2. Subject to the terms and conditions of this License Agreement, PSF hereby\ngrants Licensee a nonexclusive, royalty-free, world-wide license to reproduce,\nanalyze, test, perform and/or display publicly, prepare derivative works,\ndistribute, and otherwise use Python alone or in any derivative version,\nprovided, however, that PSF's License Agreement and PSF's notice of copyright,\ni.e., \"Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,\n2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Python Software Foundation;\nAll Rights Reserved\" are retained in Python alone or in any derivative version\nprepared by Licensee.\n\n3. In the event Licensee prepares a derivative work that is based on\nor incorporates Python or any part thereof, and wants to make\nthe derivative work available to others as provided herein, then\nLicensee hereby agrees to include in any such work a brief summary of\nthe changes made to Python.\n\n4. PSF is making Python available to Licensee on an \"AS IS\"\nbasis.  PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR\nIMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND\nDISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS\nFOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT\nINFRINGE ANY THIRD PARTY RIGHTS.\n\n5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON\nFOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS\nA RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON,\nOR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.\n\n6. This License Agreement will automatically terminate upon a material\nbreach of its terms and conditions.\n\n7. Nothing in this License Agreement shall be deemed to create any\nrelationship of agency, partnership, or joint venture between PSF and\nLicensee.  This License Agreement does not grant permission to use PSF\ntrademarks or trade name in a trademark sense to endorse or promote\nproducts or services of Licensee, or any third party.\n\n8. By copying, installing or otherwise using Python, Licensee\nagrees to be bound by the terms and conditions of this License\nAgreement.\n\n\nBEOPEN.COM LICENSE AGREEMENT FOR PYTHON 2.0\n-------------------------------------------\n\nBEOPEN PYTHON OPEN SOURCE LICENSE AGREEMENT VERSION 1\n\n1. This LICENSE AGREEMENT is between BeOpen.com (\"BeOpen\"), having an\noffice at 160 Saratoga Avenue, Santa Clara, CA 95051, and the\nIndividual or Organization (\"Licensee\") accessing and otherwise using\nthis software in source or binary form and its associated\ndocumentation (\"the Software\").\n\n2. Subject to the terms and conditions of this BeOpen Python License\nAgreement, BeOpen hereby grants Licensee a non-exclusive,\nroyalty-free, world-wide license to reproduce, analyze, test, perform\nand/or display publicly, prepare derivative works, distribute, and\notherwise use the Software alone or in any derivative version,\nprovided, however, that the BeOpen Python License is retained in the\nSoftware, alone or in any derivative version prepared by Licensee.\n\n3. BeOpen is making the Software available to Licensee on an \"AS IS\"\nbasis.  BEOPEN MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR\nIMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, BEOPEN MAKES NO AND\nDISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS\nFOR ANY PARTICULAR PURPOSE OR THAT THE USE OF THE SOFTWARE WILL NOT\nINFRINGE ANY THIRD PARTY RIGHTS.\n\n4. BEOPEN SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF THE\nSOFTWARE FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS\nAS A RESULT OF USING, MODIFYING OR DISTRIBUTING THE SOFTWARE, OR ANY\nDERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.\n\n5. This License Agreement will automatically terminate upon a material\nbreach of its terms and conditions.\n\n6. This License Agreement shall be governed by and interpreted in all\nrespects by the law of the State of California, excluding conflict of\nlaw provisions.  Nothing in this License Agreement shall be deemed to\ncreate any relationship of agency, partnership, or joint venture\nbetween BeOpen and Licensee.  This License Agreement does not grant\npermission to use BeOpen trademarks or trade names in a trademark\nsense to endorse or promote products or services of Licensee, or any\nthird party.  As an exception, the \"BeOpen Python\" logos available at\nhttp://www.pythonlabs.com/logos.html may be used according to the\npermissions granted on that web page.\n\n7. By copying, installing or otherwise using the software, Licensee\nagrees to be bound by the terms and conditions of this License\nAgreement.\n\n\nCNRI LICENSE AGREEMENT FOR PYTHON 1.6.1\n---------------------------------------\n\n1. This LICENSE AGREEMENT is between the Corporation for National\nResearch Initiatives, having an office at 1895 Preston White Drive,\nReston, VA 20191 (\"CNRI\"), and the Individual or Organization\n(\"Licensee\") accessing and otherwise using Python 1.6.1 software in\nsource or binary form and its associated documentation.\n\n2. Subject to the terms and conditions of this License Agreement, CNRI\nhereby grants Licensee a nonexclusive, royalty-free, world-wide\nlicense to reproduce, analyze, test, perform and/or display publicly,\nprepare derivative works, distribute, and otherwise use Python 1.6.1\nalone or in any derivative version, provided, however, that CNRI's\nLicense Agreement and CNRI's notice of copyright, i.e., \"Copyright (c)\n1995-2001 Corporation for National Research Initiatives; All Rights\nReserved\" are retained in Python 1.6.1 alone or in any derivative\nversion prepared by Licensee.  Alternately, in lieu of CNRI's License\nAgreement, Licensee may substitute the following text (omitting the\nquotes): \"Python 1.6.1 is made available subject to the terms and\nconditions in CNRI's License Agreement.  This Agreement together with\nPython 1.6.1 may be located on the Internet using the following\nunique, persistent identifier (known as a handle): 1895.22/1013.  This\nAgreement may also be obtained from a proxy server on the Internet\nusing the following URL: http://hdl.handle.net/1895.22/1013\".\n\n3. In the event Licensee prepares a derivative work that is based on\nor incorporates Python 1.6.1 or any part thereof, and wants to make\nthe derivative work available to others as provided herein, then\nLicensee hereby agrees to include in any such work a brief summary of\nthe changes made to Python 1.6.1.\n\n4. CNRI is making Python 1.6.1 available to Licensee on an \"AS IS\"\nbasis.  CNRI MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR\nIMPLIED.  BY WAY OF EXAMPLE, BUT NOT LIMITATION, CNRI MAKES NO AND\nDISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS\nFOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON 1.6.1 WILL NOT\nINFRINGE ANY THIRD PARTY RIGHTS.\n\n5. CNRI SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON\n1.6.1 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS\nA RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON 1.6.1,\nOR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF.\n\n6. This License Agreement will automatically terminate upon a material\nbreach of its terms and conditions.\n\n7. This License Agreement shall be governed by the federal\nintellectual property law of the United States, including without\nlimitation the federal copyright law, and, to the extent such\nU.S. federal law does not apply, by the law of the Commonwealth of\nVirginia, excluding Virginia's conflict of law provisions.\nNotwithstanding the foregoing, with regard to derivative works based\non Python 1.6.1 that incorporate non-separable material that was\npreviously distributed under the GNU General Public License (GPL), the\nlaw of the Commonwealth of Virginia shall govern this License\nAgreement only as to issues arising under or with respect to\nParagraphs 4, 5, and 7 of this License Agreement.  Nothing in this\nLicense Agreement shall be deemed to create any relationship of\nagency, partnership, or joint venture between CNRI and Licensee.  This\nLicense Agreement does not grant permission to use CNRI trademarks or\ntrade name in a trademark sense to endorse or promote products or\nservices of Licensee, or any third party.\n\n8. By clicking on the \"ACCEPT\" button where indicated, or by copying,\ninstalling or otherwise using Python 1.6.1, Licensee agrees to be\nbound by the terms and conditions of this License Agreement.\n\n        ACCEPT\n\n\nCWI LICENSE AGREEMENT FOR PYTHON 0.9.0 THROUGH 1.2\n--------------------------------------------------\n\nCopyright (c) 1991 - 1995, Stichting Mathematisch Centrum Amsterdam,\nThe Netherlands.  All rights reserved.\n\nPermission to use, copy, modify, and distribute this software and its\ndocumentation for any purpose and without fee is hereby granted,\nprovided that the above copyright notice appear in all copies and that\nboth that copyright notice and this permission notice appear in\nsupporting documentation, and that the name of Stichting Mathematisch\nCentrum or CWI not be used in advertising or publicity pertaining to\ndistribution of the software without specific, written prior\npermission.\n\nSTICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO\nTHIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE\nFOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT\nOF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - @cypress/request@3.0.10\n - aws-sign2@0.7.0\n - forever-agent@0.6.1\n - tunnel-agent@0.6.0\n\nThese packages each contain the following license:\n\nApache License\n\nVersion 2.0, January 2004\n\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n\"License\" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.\n\n\"Licensor\" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.\n\n\"Legal Entity\" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, \"control\" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.\n\n\"You\" (or \"Your\") shall mean an individual or Legal Entity exercising permissions granted by this License.\n\n\"Source\" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.\n\n\"Object\" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.\n\n\"Work\" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).\n\n\"Derivative Works\" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.\n\n\"Contribution\" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, \"submitted\" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as \"Not a Contribution.\"\n\n\"Contributor\" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.\n\n2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.\n\n3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.\n\n4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:\n\nYou must give any other recipients of the Work or Derivative Works a copy of this License; and\n\nYou must cause any modified files to carry prominent notices stating that You changed the files; and\n\nYou must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and\n\nIf the Work includes a \"NOTICE\" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.\n\n5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.\n\n6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.\n\n8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\n-----------\n\nThe following npm package may be included in this product:\n\n - ecdsa-sig-formatter@1.0.11\n\nThis package contains the following license:\n\nApache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2015 D2L Corporation\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - caseless@0.12.0\n\nThis package contains the following license:\n\nApache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n1. Definitions.\n\"License\" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.\n\"Licensor\" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.\n\"Legal Entity\" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, \"control\" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.\n\"You\" (or \"Your\") shall mean an individual or Legal Entity exercising permissions granted by this License.\n\"Source\" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.\n\"Object\" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.\n\"Work\" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).\n\"Derivative Works\" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.\n\"Contribution\" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, \"submitted\" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as \"Not a Contribution.\"\n\"Contributor\" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.\n2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.\n3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.\n4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:\nYou must give any other recipients of the Work or Derivative Works a copy of this License; and\nYou must cause any modified files to carry prominent notices stating that You changed the files; and\nYou must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and\nIf the Work includes a \"NOTICE\" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.\n5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.\n6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.\n7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.\n8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.\n9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.\nEND OF TERMS AND CONDITIONS\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - filelist@1.0.4\n - jake@10.9.4\n\nThese packages each contain the following license:\n\nApache-2.0\n\n-----------\n\nThe following npm package may be included in this product:\n\n - qs@6.14.2\n\nThis package contains the following license:\n\nBSD 3-Clause License\n\nCopyright (c) 2014, Nathan LaFreniere and other [contributors](https://github.com/ljharb/qs/graphs/contributors)\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this\n   list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice,\n   this list of conditions and the following disclaimer in the documentation\n   and/or other materials provided with the distribution.\n\n3. Neither the name of the copyright holder nor the names of its\n   contributors may be used to endorse or promote products derived from\n   this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - sprintf-js@1.0.3\n\nThis package contains the following license:\n\nCopyright (c) 2007-2014, Alexandru Marasteanu <hello [at) alexei (dot] ro>\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n* Redistributions of source code must retain the above copyright\n  notice, this list of conditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright\n  notice, this list of conditions and the following disclaimer in the\n  documentation and/or other materials provided with the distribution.\n* Neither the name of this software nor the names of its contributors may be\n  used to endorse or promote products derived from this software without\n  specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR\nANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS\nSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - async@2.6.4\n - async@3.2.6\n\nThese packages each contain the following license:\n\nCopyright (c) 2010-2018 Caolan McMahon\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - iconv-lite@0.4.24\n - iconv-lite@0.7.0\n\nThese packages each contain the following license:\n\nCopyright (c) 2011 Alexander Shtuchkin\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - ip-address@10.0.1\n\nThis package contains the following license:\n\nCopyright (C) 2011 by Beau Gunderson\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - combined-stream@1.0.8\n - delayed-stream@1.0.0\n\nThese packages each contain the following license:\n\nCopyright (c) 2011 Debuggable Limited <felix@debuggable.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - ws@8.18.3\n\nThis package contains the following license:\n\nCopyright (c) 2011 Einar Otto Stangvik <einaros@gmail.com>\nCopyright (c) 2013 Arnout Kazemier and contributors\nCopyright (c) 2016 Luigi Pinca and contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - asn1@0.2.6\n\nThis package contains the following license:\n\nCopyright (c) 2011 Mark Cavage, All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - color-convert@1.9.3\n - color-convert@2.0.1\n\nThese packages each contain the following license:\n\nCopyright (c) 2011-2016 Heather Arthur <fayearthur@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - ipaddr.js@1.9.1\n\nThis package contains the following license:\n\nCopyright (C) 2011-2017 whitequark <whitequark@whitequark.org>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - mkdirp@3.0.1\n\nThis package contains the following license:\n\nCopyright (c) 2011-2023 James Halliday (mail@substack.net) and Isaac Z. Schlueter (i@izs.me)\n\nThis project is free software released under the MIT license:\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - form-data@4.0.4\n\nThis package contains the following license:\n\nCopyright (c) 2012 Felix Geisendörfer (felix@debuggable.com) and contributors\n\n Permission is hereby granted, free of charge, to any person obtaining a copy\n of this software and associated documentation files (the \"Software\"), to deal\n in the Software without restriction, including without limitation the rights\n to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n copies of the Software, and to permit persons to whom the Software is\n furnished to do so, subject to the following conditions:\n\n The above copyright notice and this permission notice shall be included in\n all copies or substantial portions of the Software.\n\n THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\n THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - escodegen@2.1.0\n\nThis package contains the following license:\n\nCopyright (C) 2012 Yusuke Suzuki (twitter: @Constellation) and other contributors.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\nTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - archiver@3.1.1\n\nThis package contains the following license:\n\nCopyright (c) 2012-2014 Chris Talkington, contributors.\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - url-template@2.0.8\n\nThis package contains the following license:\n\nCopyright (c) 2012-2014, Bram Stein\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without \nmodification, are permitted provided that the following conditions \nare met:\n \n 1. Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer. \n 2. Redistributions in binary form must reproduce the above copyright \n    notice, this list of conditions and the following disclaimer in the \n    documentation and/or other materials provided with the distribution. \n 3. The name of the author may not be used to endorse or promote products \n    derived from this software without specific prior written permission. \n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR \"AS IS\" AND ANY EXPRESS OR IMPLIED \nWARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \nMERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO \nEVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, \nINDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, \nBUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, \nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY \nOF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING \nNEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, \nEVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - extsprintf@1.3.0\n - jsprim@2.0.2\n\nThese packages each contain the following license:\n\nCopyright (c) 2012, Joyent, Inc. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE\n\n-----------\n\nThe following npm package may be included in this product:\n\n - ast-types@0.13.4\n\nThis package contains the following license:\n\nCopyright (c) 2013 Ben Newman <bn@cs.stanford.edu>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY\nCLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,\nTORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - performance-now@2.1.0\n\nThis package contains the following license:\n\nCopyright (c) 2013 Braveg1rl\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - jwa@2.0.1\n - jws@4.0.1\n\nThese packages each contain the following license:\n\nCopyright (c) 2013 Brian J. Brennan\n\nPermission is hereby granted, free of charge, to any person obtaining a copy \nof this software and associated documentation files (the \"Software\"), to deal in \nthe Software without restriction, including without limitation the rights to use, \ncopy, modify, merge, publish, distribute, sublicense, and/or sell copies of the \nSoftware, and to permit persons to whom the Software is furnished to do so, \nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all \ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, \nINCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR \nPURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE\nFOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - keytar@7.9.0\n\nThis package contains the following license:\n\nCopyright (c) 2013 GitHub Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - lazystream@1.0.1\n\nThis package contains the following license:\n\nCopyright (c) 2013 J. Pommerening, contributors.\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - ignore@5.3.2\n\nThis package contains the following license:\n\nCopyright (c) 2013 Kael Zhang <i@kael.me>, contributors\nhttp://kael.me/\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - function-bind@1.1.2\n\nThis package contains the following license:\n\nCopyright (c) 2013 Raynos.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - buffer-equal-constant-time@1.0.1\n\nThis package contains the following license:\n\nCopyright (c) 2013, GoInstant Inc., a salesforce.com company\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\n* Neither the name of salesforce.com, nor GoInstant, nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - zip-stream@2.1.3\n\nThis package contains the following license:\n\nCopyright (c) 2014 Chris Talkington, contributors.\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - compress-commons@2.1.1\n - crc32-stream@3.0.1\n\nThese packages each contain the following license:\n\nCopyright (c) 2014 Chris Talkington, contributors.\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - archiver-utils@2.1.0\n\nThis package contains the following license:\n\nCopyright (c) 2015 Chris Talkington.\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - fastq@1.19.1\n\nThis package contains the following license:\n\nCopyright (c) 2015-2020, Matteo Collina <matteo.collina@gmail.com>\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - cli-width@3.0.0\n\nThis package contains the following license:\n\nCopyright (c) 2015, Ilya Radchenko <ilya@burstcreations.com>\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - cli-width@4.1.0\n\nThis package contains the following license:\n\nCopyright (c) 2015, Ilya Radchenko <knownasilya@gmail.com>\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - tough-cookie@5.1.2\n\nThis package contains the following license:\n\nCopyright (c) 2015, Salesforce.com, Inc.\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\n3. Neither the name of Salesforce.com nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - setprototypeof@1.2.0\n\nThis package contains the following license:\n\nCopyright (c) 2015, Wes Todd\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY\nSPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION\nOF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN\nCONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - verror@1.10.0\n\nThis package contains the following license:\n\nCopyright (c) 2016, Joyent, Inc. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - tldts-core@6.1.86\n - tldts@6.1.86\n\nThese packages each contain the following license:\n\nCopyright (c) 2017 Thomas Parisot, 2018 Rémi Berson\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and\nassociated documentation files (the \"Software\"), to deal in the Software without restriction,\nincluding without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,\nand/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\n WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - csstype@3.2.3\n\nThis package contains the following license:\n\nCopyright (c) 2017-2018 Fredrik Nicol\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - object-treeify@1.1.33\n\nThis package contains the following license:\n\nCopyright (c) 2019 Lukas Siemon\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - basic-ftp@5.2.0\n\nThis package contains the following license:\n\nCopyright (c) 2019 Patrick Juchli\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - filesize@6.4.0\n\nThis package contains the following license:\n\nCopyright (c) 2021, Jason Mulligan\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this\n  list of conditions and the following disclaimer.\n\n* Redistributions in binary form must reproduce the above copyright notice,\n  this list of conditions and the following disclaimer in the documentation\n  and/or other materials provided with the distribution.\n\n* Neither the name of filesize nor the names of its\n  contributors may be used to endorse or promote products derived from\n  this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - inquirer@8.2.7\n\nThis package contains the following license:\n\nCopyright (c) 2022 Simon Boudrias\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - chardet@2.1.1\n\nThis package contains the following license:\n\nCopyright (C) 2024 Dmitry Shirokov\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - @inquirer/ansi@1.0.2\n - @inquirer/checkbox@4.3.2\n - @inquirer/confirm@5.1.21\n - @inquirer/core@10.3.2\n - @inquirer/editor@4.2.23\n - @inquirer/expand@4.0.23\n - @inquirer/external-editor@1.0.3\n - @inquirer/figures@1.0.15\n - @inquirer/input@4.3.1\n - @inquirer/number@3.0.23\n - @inquirer/password@4.0.23\n - @inquirer/prompts@7.10.1\n - @inquirer/rawlist@4.1.11\n - @inquirer/search@3.2.2\n - @inquirer/select@4.4.2\n - @inquirer/type@3.0.10\n\nThese packages each contain the following license:\n\nCopyright (c) 2025 Simon Boudrias\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - @octokit/openapi-types@27.0.0\n\nThis package contains the following license:\n\nCopyright (c) GitHub 2025 - Licensed as MIT.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - tslib@2.8.1\n\nThis package contains the following license:\n\nCopyright (c) Microsoft Corporation.\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - clone@1.0.4\n\nThis package contains the following license:\n\nCopyright © 2011-2015 Paul Vorbach <paul@vorba.ch>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the “Software”), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, OUT OF OR IN CONNECTION WITH THE\nSOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - ieee754@1.2.1\n\nThis package contains the following license:\n\nCopyright 2008 Fair Oaks Labs, Inc.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\n3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - uri-js@4.4.1\n\nThis package contains the following license:\n\nCopyright 2011 Gary Court. All rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n1.\tRedistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n2.\tRedistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY GARY COURT \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GARY COURT OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\nThe views and conclusions contained in the software and documentation are those of the authors and should not be interpreted as representing official policies, either expressed or implied, of Gary Court.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - cardinal@2.1.1\n - redeyed@2.1.1\n\nThese packages each contain the following license:\n\nCopyright 2012 Thorsten Lorenz. \nAll rights reserved.\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - lodash.isboolean@3.0.3\n - lodash.isnumber@3.0.3\n - lodash.isstring@4.0.1\n\nThese packages each contain the following license:\n\nCopyright 2012-2016 The Dojo Foundation <http://dojofoundation.org/>\nBased on Underscore.js, copyright 2009-2016 Jeremy Ashkenas,\nDocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - aws4@1.13.2\n\nThis package contains the following license:\n\nCopyright 2013 Michael Hart (michael.hart.au@gmail.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - ansicolors@0.3.2\n\nThis package contains the following license:\n\nCopyright 2013 Thorsten Lorenz. \nAll rights reserved.\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - make-error@1.3.6\n\nThis package contains the following license:\n\nCopyright 2014 Julien Fontanet\n\nPermission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - json-parse-better-errors@1.0.2\n\nThis package contains the following license:\n\nCopyright 2017 Kat Marchán\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - @jridgewell/resolve-uri@3.1.2\n\nThis package contains the following license:\n\nCopyright 2019 Justin Ridgewell <jridgewell@google.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - @jridgewell/trace-mapping@0.3.9\n\nThis package contains the following license:\n\nCopyright 2022 Justin Ridgewell <justin@ridgewell.name>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - fdir@6.5.0\n\nThis package contains the following license:\n\nCopyright 2023 Abdullah Atta\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - @jridgewell/sourcemap-codec@1.5.5\n\nThis package contains the following license:\n\nCopyright 2024 Justin Ridgewell <justin@ridgewell.name>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - getpass@0.1.7\n - http-signature@1.4.0\n - sshpk@1.18.0\n\nThese packages each contain the following license:\n\nCopyright Joyent, Inc. All rights reserved.\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - lodash.defaults@4.2.0\n - lodash.difference@4.5.0\n - lodash.flatten@4.4.0\n - lodash.includes@4.3.0\n - lodash.isinteger@4.0.4\n - lodash.isplainobject@4.0.6\n - lodash.once@4.1.1\n - lodash.throttle@4.1.1\n - lodash.union@4.6.0\n\nThese packages each contain the following license:\n\nCopyright jQuery Foundation and other contributors <https://jquery.org/>\n\nBased on Underscore.js, copyright Jeremy Ashkenas,\nDocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>\n\nThis software consists of voluntary contributions made by many\nindividuals. For exact contribution history, see the revision history\navailable at https://github.com/lodash/lodash\n\nThe following license applies to all parts of this software except as\ndocumented below:\n\n====\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n====\n\nCopyright and related rights for sample code are waived via CC0. Sample\ncode is defined as all source code displayed within the prose of the\ndocumentation.\n\nCC0: http://creativecommons.org/publicdomain/zero/1.0/\n\n====\n\nFiles located in the node_modules and vendor directories are externally\nmaintained libraries used by this software which have their own\nlicenses; we recommend you read them, as their terms may differ from the\nterms above.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - esprima@4.0.1\n\nThis package contains the following license:\n\nCopyright JS Foundation and other contributors, https://js.foundation/\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\nTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - emoji-regex@10.6.0\n - emoji-regex@8.0.0\n - punycode@2.3.1\n\nThese packages each contain the following license:\n\nCopyright Mathias Bynens <https://mathiasbynens.be/>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - core-util-is@1.0.2\n\nThis package contains the following license:\n\nCopyright Node.js contributors. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - lodash@4.17.23\n\nThis package contains the following license:\n\nCopyright OpenJS Foundation and other contributors <https://openjsf.org/>\n\nBased on Underscore.js, copyright Jeremy Ashkenas,\nDocumentCloud and Investigative Reporters & Editors <http://underscorejs.org/>\n\nThis software consists of voluntary contributions made by many\nindividuals. For exact contribution history, see the revision history\navailable at https://github.com/lodash/lodash\n\nThe following license applies to all parts of this software except as\ndocumented below:\n\n====\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n====\n\nCopyright and related rights for sample code are waived via CC0. Sample\ncode is defined as all source code displayed within the prose of the\ndocumentation.\n\nCC0: http://creativecommons.org/publicdomain/zero/1.0/\n\n====\n\nFiles located in the node_modules and vendor directories are externally\nmaintained libraries used by this software which have their own\nlicenses; we recommend you read them, as their terms may differ from the\nterms above.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - json-schema@0.4.0\n\nThis package contains the following license:\n\nDojo is available under *either* the terms of the BSD 3-Clause \"New\" License *or* the\nAcademic Free License version 2.1. As a recipient of Dojo, you may choose which\nlicense to receive this code under (except as noted in per-module LICENSE\nfiles). Some modules may not be the copyright of the Dojo Foundation. These\nmodules contain explicit declarations of copyright in both the LICENSE files in\nthe directories in which they reside and in the code itself. No external\ncontributions are allowed under licenses which are fundamentally incompatible\nwith the AFL-2.1 OR and BSD-3-Clause licenses that Dojo is distributed under.\n\nThe text of the AFL-2.1 and BSD-3-Clause licenses is reproduced below. \n\n-------------------------------------------------------------------------------\nBSD 3-Clause \"New\" License:\n**********************\n\nCopyright (c) 2005-2015, The Dojo Foundation\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  * Redistributions of source code must retain the above copyright notice, this\n    list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright notice,\n    this list of conditions and the following disclaimer in the documentation\n    and/or other materials provided with the distribution.\n  * Neither the name of the Dojo Foundation nor the names of its contributors\n    may be used to endorse or promote products derived from this software\n    without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND\nANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED\nWARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE\nDISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE\nFOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR\nSERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER\nCAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,\nOR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE\nOF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-------------------------------------------------------------------------------\nThe Academic Free License, v. 2.1:\n**********************************\n\nThis Academic Free License (the \"License\") applies to any original work of\nauthorship (the \"Original Work\") whose owner (the \"Licensor\") has placed the\nfollowing notice immediately following the copyright notice for the Original\nWork:\n\nLicensed under the Academic Free License version 2.1\n\n1) Grant of Copyright License. Licensor hereby grants You a world-wide,\nroyalty-free, non-exclusive, perpetual, sublicenseable license to do the\nfollowing:\n\na) to reproduce the Original Work in copies;\n\nb) to prepare derivative works (\"Derivative Works\") based upon the Original\nWork;\n\nc) to distribute copies of the Original Work and Derivative Works to the\npublic;\n\nd) to perform the Original Work publicly; and\n\ne) to display the Original Work publicly.\n\n2) Grant of Patent License. Licensor hereby grants You a world-wide,\nroyalty-free, non-exclusive, perpetual, sublicenseable license, under patent\nclaims owned or controlled by the Licensor that are embodied in the Original\nWork as furnished by the Licensor, to make, use, sell and offer for sale the\nOriginal Work and Derivative Works.\n\n3) Grant of Source Code License. The term \"Source Code\" means the preferred\nform of the Original Work for making modifications to it and all available\ndocumentation describing how to modify the Original Work. Licensor hereby\nagrees to provide a machine-readable copy of the Source Code of the Original\nWork along with each copy of the Original Work that Licensor distributes.\nLicensor reserves the right to satisfy this obligation by placing a\nmachine-readable copy of the Source Code in an information repository\nreasonably calculated to permit inexpensive and convenient access by You for as\nlong as Licensor continues to distribute the Original Work, and by publishing\nthe address of that information repository in a notice immediately following\nthe copyright notice that applies to the Original Work.\n\n4) Exclusions From License Grant. Neither the names of Licensor, nor the names\nof any contributors to the Original Work, nor any of their trademarks or\nservice marks, may be used to endorse or promote products derived from this\nOriginal Work without express prior written permission of the Licensor. Nothing\nin this License shall be deemed to grant any rights to trademarks, copyrights,\npatents, trade secrets or any other intellectual property of Licensor except as\nexpressly stated herein. No patent license is granted to make, use, sell or\noffer to sell embodiments of any patent claims other than the licensed claims\ndefined in Section 2. No right is granted to the trademarks of Licensor even if\nsuch marks are included in the Original Work. Nothing in this License shall be\ninterpreted to prohibit Licensor from licensing under different terms from this\nLicense any Original Work that Licensor otherwise would have a right to\nlicense.\n\n5) This section intentionally omitted.\n\n6) Attribution Rights. You must retain, in the Source Code of any Derivative\nWorks that You create, all copyright, patent or trademark notices from the\nSource Code of the Original Work, as well as any notices of licensing and any\ndescriptive text identified therein as an \"Attribution Notice.\" You must cause\nthe Source Code for any Derivative Works that You create to carry a prominent\nAttribution Notice reasonably calculated to inform recipients that You have\nmodified the Original Work.\n\n7) Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that\nthe copyright in and to the Original Work and the patent rights granted herein\nby Licensor are owned by the Licensor or are sublicensed to You under the terms\nof this License with the permission of the contributor(s) of those copyrights\nand patent rights. Except as expressly stated in the immediately proceeding\nsentence, the Original Work is provided under this License on an \"AS IS\" BASIS\nand WITHOUT WARRANTY, either express or implied, including, without limitation,\nthe warranties of NON-INFRINGEMENT, MERCHANTABILITY or FITNESS FOR A PARTICULAR\nPURPOSE. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU.\nThis DISCLAIMER OF WARRANTY constitutes an essential part of this License. No\nlicense to Original Work is granted hereunder except under this disclaimer.\n\n8) Limitation of Liability. Under no circumstances and under no legal theory,\nwhether in tort (including negligence), contract, or otherwise, shall the\nLicensor be liable to any person for any direct, indirect, special, incidental,\nor consequential damages of any character arising as a result of this License\nor the use of the Original Work including, without limitation, damages for loss\nof goodwill, work stoppage, computer failure or malfunction, or any and all\nother commercial damages or losses. This limitation of liability shall not\napply to liability for death or personal injury resulting from Licensor's\nnegligence to the extent applicable law prohibits such limitation. Some\njurisdictions do not allow the exclusion or limitation of incidental or\nconsequential damages, so this exclusion and limitation may not apply to You.\n\n9) Acceptance and Termination. If You distribute copies of the Original Work or\na Derivative Work, You must make a reasonable effort under the circumstances to\nobtain the express assent of recipients to the terms of this License. Nothing\nelse but this License (or another written agreement between Licensor and You)\ngrants You permission to create Derivative Works based upon the Original Work\nor to exercise any of the rights granted in Section 1 herein, and any attempt\nto do so except under the terms of this License (or another written agreement\nbetween Licensor and You) is expressly prohibited by U.S. copyright law, the\nequivalent laws of other countries, and by international treaty. Therefore, by\nexercising any of the rights granted to You in Section 1 herein, You indicate\nYour acceptance of this License and all of its terms and conditions.\n\n10) Termination for Patent Action. This License shall terminate automatically\nand You may no longer exercise any of the rights granted to You by this License\nas of the date You commence an action, including a cross-claim or counterclaim,\nagainst Licensor or any licensee alleging that the Original Work infringes a\npatent. This termination provision shall not apply for an action alleging\npatent infringement by combinations of the Original Work with other software or\nhardware.\n\n11) Jurisdiction, Venue and Governing Law. Any action or suit relating to this\nLicense may be brought only in the courts of a jurisdiction wherein the\nLicensor resides or in which Licensor conducts its primary business, and under\nthe laws of that jurisdiction excluding its conflict-of-law provisions. The\napplication of the United Nations Convention on Contracts for the International\nSale of Goods is expressly excluded. Any use of the Original Work outside the\nscope of this License or after its termination shall be subject to the\nrequirements and penalties of the U.S. Copyright Act, 17 U.S.C. Â§ 101 et\nseq., the equivalent laws of other countries, and international treaty. This\nsection shall survive the termination of this License.\n\n12) Attorneys Fees. In any action to enforce the terms of this License or\nseeking damages relating thereto, the prevailing party shall be entitled to\nrecover its costs and expenses, including, without limitation, reasonable\nattorneys' fees and costs incurred in connection with such action, including\nany appeal of such action. This section shall survive the termination of this\nLicense.\n\n13) Miscellaneous. This License represents the complete agreement concerning\nthe subject matter hereof. If any provision of this License is held to be\nunenforceable, such provision shall be reformed only to the extent necessary to\nmake it enforceable.\n\n14) Definition of \"You\" in This License. \"You\" throughout this License, whether\nin upper or lower case, means an individual or a legal entity exercising rights\nunder, and complying with all of the terms of, this License. For legal\nentities, \"You\" includes any entity that controls, is controlled by, or is\nunder common control with you. For purposes of this definition, \"control\" means\n(i) the power, direct or indirect, to cause the direction or management of such\nentity, whether by contract or otherwise, or (ii) ownership of fifty percent\n(50%) or more of the outstanding shares, or (iii) beneficial ownership of such\nentity.\n\n15) Right to Use. You may use the Original Work in all ways not otherwise\nrestricted or conditioned by this License or by law, and Licensor promises not\nto interfere with or be responsible for such uses by You.\n\nThis license is Copyright (C) 2003-2004 Lawrence E. Rosen. All rights reserved.\nPermission is hereby granted to copy and distribute this license without\nmodification. This license may not be modified without the express written\npermission of its copyright owner.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - http-call@5.3.0\n - log-chopper@1.0.2\n\nThese packages each contain the following license:\n\nISC\n\n-----------\n\nThe following npm package may be included in this product:\n\n - picocolors@1.1.1\n\nThis package contains the following license:\n\nISC License\n\nCopyright (c) 2021-2024 Oleksii Raspopov, Kostiantyn Denysov, Anton Verinov\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - ansis@3.17.0\n\nThis package contains the following license:\n\nISC License\n\nCopyright (c) 2025, webdiscus\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - jsbn@0.1.1\n\nThis package contains the following license:\n\nLicensing\n---------\n\nThis software is covered under the following copyright:\n\n/*\n * Copyright (c) 2003-2005  Tom Wu\n * All Rights Reserved.\n *\n * Permission is hereby granted, free of charge, to any person obtaining\n * a copy of this software and associated documentation files (the\n * \"Software\"), to deal in the Software without restriction, including\n * without limitation the rights to use, copy, modify, merge, publish,\n * distribute, sublicense, and/or sell copies of the Software, and to\n * permit persons to whom the Software is furnished to do so, subject to\n * the following conditions:\n *\n * The above copyright notice and this permission notice shall be\n * included in all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS-IS\" AND WITHOUT WARRANTY OF ANY KIND, \n * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY \n * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.  \n *\n * IN NO EVENT SHALL TOM WU BE LIABLE FOR ANY SPECIAL, INCIDENTAL,\n * INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY DAMAGES WHATSOEVER\n * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER OR NOT ADVISED OF\n * THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF LIABILITY, ARISING OUT\n * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n *\n * In addition, the following condition applies:\n *\n * All redistributions must retain an intact copy of this copyright notice\n * and disclaimer.\n */\n\nAddress all questions regarding this license to:\n\n  Tom Wu\n  tjw@cs.Stanford.EDU\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - @alcalzone/ansi-tokenize@0.1.3\n - assert-plus@1.0.0\n - change-case@5.4.4\n - cookie-signature@1.0.6\n - csv-generate@4.5.0\n - csv-stringify@6.6.0\n - degenerator@5.0.1\n - isarray@1.0.0\n - keychain@1.5.0\n - netmask@2.0.2\n - tr46@0.0.3\n - undici-types@5.26.5\n\nThese packages each contain the following license:\n\nMIT\n\n-----------\n\nThe following npm package may be included in this product:\n\n - acorn-walk@8.3.4\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (C) 2012-2020 by various contributors (see AUTHORS)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - object-inspect@1.13.4\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2013 James Halliday\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - brace-expansion@1.1.12\n - brace-expansion@2.0.2\n\nThese packages each contain the following license:\n\nMIT License\n\nCopyright (c) 2013 Julian Gruber <julian@juliangruber.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - toidentifier@1.0.1\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2016 Douglas Christopher Wilson <doug@somethingdoug.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - has-symbols@1.1.0\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2016 Jordan Harband\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - node-abi@3.79.0\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2016 Lukas Geiger\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - fast-deep-equal@3.1.3\n - json-schema-traverse@0.4.1\n\nThese packages each contain the following license:\n\nMIT License\n\nCopyright (c) 2017 Evgeny Poberezkin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - arg@4.1.3\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2017-2019 Zeit, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - napi-build-utils@2.0.0\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2018 inspiredware\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - safer-buffer@2.1.2\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2018 Nikita Skovoroda <chalkerx@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - @oclif/core@2.16.0\n - @oclif/core@4.8.0\n - @oclif/plugin-autocomplete@3.2.39\n - @oclif/plugin-help@6.2.36\n - @oclif/plugin-not-found@3.2.73\n - @oclif/plugin-update@3.2.4\n - @oclif/plugin-version@2.2.36\n - @oclif/table@0.4.14\n\nThese packages each contain the following license:\n\nMIT License\n\nCopyright (c) 2018 Salesforce.com\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - side-channel-weakmap@1.0.2\n - side-channel@1.1.0\n\nThese packages each contain the following license:\n\nMIT License\n\nCopyright (c) 2019 Jordan Harband\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - create-require@1.1.1\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2020\n\nMaël Nison <nison.mael@gmail.com>\nPaul Soporan <paul.soporan@gmail.com>\nPooya Parsa <pyapar@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - get-package-type@0.1.0\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2020 CFWare, LLC\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - hash-wasm@4.12.0\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2020 Dani Biró\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\nEmbedded C implementations might use other, similarly permissive licenses.\nCheck the beginning of the files from the /src directory.\n\nSpecial thank you to the authors of original C algorithms:\n- Alexander Peslyak <solar@openwall.com>\n- Aleksey Kravchenko <rhash.admin@gmail.com>\n- Colin Percival\n- Stephan Brumme <create@stephan-brumme.com>\n- Steve Reid <steve@edmweb.com>\n- Samuel Neves <sneves@dei.uc.pt>\n- Solar Designer <solar@openwall.com>\n- Project Nayuki\n- ARM Limited\n- Yanbo Li dreamfly281@gmail.com, goldboar@163.comYanbo Li\n- Mark Adler\n- Yann Collet\n\n-----------\n\nThe following npm package may be included in this product:\n\n - get-intrinsic@1.3.0\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2020 Jordan Harband\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - fastest-levenshtein@1.0.16\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2020 Kasper Unn Weihe\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - @discoveryjs/json-ext@0.5.7\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2020 Roman Dvornov <rdvornov@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - has-tostringtag@1.0.2\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2021 Inspect JS\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - lilconfig@3.1.3\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2022 Anton Kastritskiy\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - es-set-tostringtag@2.1.0\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2022 ECMAScript Shims\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - gopd@1.2.0\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2022 Jordan Harband\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - yoga-wasm-web@0.3.3\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2022 Shu Ding\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - fast-content-type-parse@3.0.0\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2023 The Fastify Team\n\nThe Fastify team members are listed at https://github.com/fastify/fastify#team\nand in the README file.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - dunder-proto@1.0.1\n - math-intrinsics@1.1.0\n\nThese packages each contain the following license:\n\nMIT License\n\nCopyright (c) 2024 ECMAScript Shims\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - call-bind-apply-helpers@1.0.2\n - call-bound@1.0.4\n - es-define-property@1.0.1\n - es-errors@1.3.0\n - es-object-atoms@1.1.1\n - side-channel-list@1.0.0\n - side-channel-map@1.0.1\n\nThese packages each contain the following license:\n\nMIT License\n\nCopyright (c) 2024 Jordan Harband\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - tinyglobby@0.2.15\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2024 Madeline Gurriarán\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - get-proto@1.0.1\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) 2025 Jordan Harband\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - slice-ansi@4.0.0\n - slice-ansi@5.0.0\n - slice-ansi@7.1.2\n\nThese packages each contain the following license:\n\nMIT License\n\nCopyright (c) DC <threedeecee@gmail.com>\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - react-reconciler@0.29.2\n - scheduler@0.23.2\n\nThese packages each contain the following license:\n\nMIT License\n\nCopyright (c) Facebook, Inc. and its affiliates.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - hyperlinker@1.0.0\n - supports-hyperlinks@2.3.0\n\nThese packages each contain the following license:\n\nMIT License\n\nCopyright (c) James Talmage <james@talmage.io> (github.com/jamestalmage)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - hasown@2.0.2\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) Jordan Harband and contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - astral-regex@2.0.0\n - dir-glob@3.0.1\n - shebang-command@2.0.0\n\nThese packages each contain the following license:\n\nMIT License\n\nCopyright (c) Kevin Mårtensson <kevinmartensson@gmail.com> (github.com/kevva)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - @tsconfig/node10@1.0.12\n - @tsconfig/node12@1.0.11\n - @tsconfig/node14@1.0.3\n - @tsconfig/node16@1.0.4\n\nThese packages each contain the following license:\n\nMIT License\n\nCopyright (c) Microsoft Corporation.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - ansi-escapes@4.3.2\n - ansi-escapes@7.2.0\n - ansi-regex@6.2.2\n - ansi-styles@6.2.3\n - auto-bind@5.0.1\n - bundle-name@4.1.0\n - chalk@5.6.2\n - clean-stack@3.0.1\n - cli-boxes@3.0.0\n - cli-cursor@4.0.0\n - cli-spinners@2.9.2\n - cli-truncate@4.0.0\n - decompress-response@6.0.0\n - default-browser-id@5.0.0\n - default-browser@5.2.1\n - define-lazy-prop@3.0.0\n - environment@1.1.0\n - escape-string-regexp@4.0.0\n - figures@3.2.0\n - get-east-asian-width@1.4.0\n - indent-string@5.0.0\n - is-docker@2.2.1\n - is-docker@3.0.0\n - is-fullwidth-code-point@4.0.0\n - is-fullwidth-code-point@5.1.0\n - is-in-ci@0.1.0\n - is-inside-container@1.0.0\n - is-stream@2.0.1\n - is-unicode-supported@0.1.0\n - is-wsl@3.1.0\n - log-symbols@4.1.0\n - mimic-response@3.1.0\n - onetime@5.1.2\n - open@10.2.0\n - ora@5.4.1\n - restore-cursor@4.0.0\n - run-applescript@7.1.0\n - string-width@7.2.0\n - strip-ansi@7.1.2\n - supports-color@8.1.1\n - type-fest@4.41.0\n - widest-line@5.0.0\n - wrap-ansi@7.0.0\n - wrap-ansi@9.0.2\n - wsl-utils@0.1.0\n - yoctocolors-cjs@2.1.3\n\nThese packages each contain the following license:\n\nMIT License\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https://sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - type-fest@0.21.3\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (https:/sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - ansi-regex@3.0.1\n - ansi-regex@5.0.1\n - ansi-styles@3.2.1\n - ansi-styles@4.3.0\n - array-union@2.1.0\n - chalk@2.4.2\n - chalk@4.1.2\n - cli-cursor@3.1.0\n - escape-string-regexp@2.0.0\n - globby@11.1.0\n - has-flag@3.0.0\n - has-flag@4.0.0\n - indent-string@4.0.0\n - is-fullwidth-code-point@3.0.0\n - is-interactive@1.0.0\n - is-plain-obj@2.1.0\n - is-wsl@2.2.0\n - mimic-fn@2.1.0\n - p-event@2.3.1\n - p-timeout@2.0.1\n - parse-json@4.0.0\n - path-key@3.1.1\n - path-type@4.0.0\n - restore-cursor@3.1.0\n - shebang-regex@3.0.0\n - slash@3.0.0\n - string-width@2.1.1\n - string-width@4.2.3\n - strip-ansi@4.0.0\n - strip-ansi@6.0.1\n - supports-color@5.5.0\n - supports-color@7.2.0\n - widest-line@3.1.0\n - wrap-ansi@6.2.0\n - yn@3.1.1\n\nThese packages each contain the following license:\n\nMIT License\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - patch-console@2.0.0\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) Vadim Demedes <vadimdemedes@hey.com> (https://vadimdemedes.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - ink@5.0.1\n\nThis package contains the following license:\n\nMIT License\n\nCopyright (c) Vadym Demedes <vadimdemedes@hey.com> (github.com/vadimdemedes)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - colors@1.4.0\n\nThis package contains the following license:\n\nMIT License\n\nOriginal Library\n  - Copyright (c) Marak Squires\n\nAdditional Functionality\n - Copyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - @tootallnate/quickjs-emscripten@0.23.0\n\nThis package contains the following license:\n\nMIT License\n\nquickjs-emscripten copyright (c) 2019 Jake Teton-Landis\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - @octokit/plugin-paginate-rest@14.0.0\n - @octokit/plugin-rest-endpoint-methods@17.0.0\n - @octokit/types@16.0.0\n\nThese packages each contain the following license:\n\nMIT License Copyright (c) 2019 Octokit contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - @octokit/plugin-request-log@6.0.0\n\nThis package contains the following license:\n\nMIT License Copyright (c) 2020 Octokit contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice (including the next paragraph) shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - byline@5.0.0\n\nThis package contains the following license:\n\nnode-byline (C) 2011-2015 John Hewson\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - readable-stream@2.3.8\n - readable-stream@3.6.2\n\nThese packages each contain the following license:\n\nNode.js is licensed for use as follows:\n\n\"\"\"\nCopyright Node.js contributors. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n\"\"\"\n\nThis license applies to parts of Node.js originating from the\nhttps://github.com/joyent/node repository:\n\n\"\"\"\nCopyright Joyent, Inc. and other Node contributors. All rights reserved.\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n\"\"\"\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - string_decoder@1.1.1\n - string_decoder@1.3.0\n\nThese packages each contain the following license:\n\nNode.js is licensed for use as follows:\n\n\"\"\"\nCopyright Node.js contributors. All rights reserved.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n\"\"\"\n\nThis license applies to parts of Node.js originating from the\nhttps://github.com/joyent/node repository:\n\n\"\"\"\nCopyright Joyent, Inc. and other Node contributors. All rights reserved.\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to\ndeal in the Software without restriction, including without limitation the\nrights to use, copy, modify, merge, publish, distribute, sublicense, and/or\nsell copies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\nIN THE SOFTWARE.\n\"\"\"\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - estraverse@5.3.0\n - esutils@2.0.3\n\nThese packages each contain the following license:\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions are met:\n\n  * Redistributions of source code must retain the above copyright\n    notice, this list of conditions and the following disclaimer.\n  * Redistributions in binary form must reproduce the above copyright\n    notice, this list of conditions and the following disclaimer in the\n    documentation and/or other materials provided with the distribution.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\nAND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\nIMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\nARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY\nDIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES\n(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;\nLOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND\nON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\nTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - diff@4.0.4\n\nThis package contains the following license:\n\nSoftware License Agreement (BSD License)\n\nCopyright (c) 2009-2015, Kevin Decker <kpdecker@gmail.com>\n\nAll rights reserved.\n\nRedistribution and use of this software in source and binary forms, with or without modification,\nare permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above\n  copyright notice, this list of conditions and the\n  following disclaimer.\n\n* Redistributions in binary form must reproduce the above\n  copyright notice, this list of conditions and the\n  following disclaimer in the documentation and/or other\n  materials provided with the distribution.\n\n* Neither the name of Kevin Decker nor the names of its\n  contributors may be used to endorse or promote products\n  derived from this software without specific prior\n  written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR\nCONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL\nDAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER\nIN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT\nOF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - http-status@1.8.1\n\nThis package contains the following license:\n\nSoftware License Agreement (BSD License)\n========================================\nCopyright (c) 2008-2010, SARL Adaltas.\n\nAll rights reserved.\n\nRedistribution and use of this software in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n-   Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n\n-   Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n\n-   Neither the name of SARL Adaltas nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission of the SARL Adaltas.\n\nTHIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - bcrypt-pbkdf@1.0.2\n\nThis package contains the following license:\n\nThe Blowfish portions are under the following license:\n\nBlowfish block cipher for OpenBSD\nCopyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>\nAll rights reserved.\n\nImplementation advice by David Mazieres <dm@lcs.mit.edu>.\n\nRedistribution and use in source and binary forms, with or without\nmodification, are permitted provided that the following conditions\nare met:\n1. Redistributions of source code must retain the above copyright\n   notice, this list of conditions and the following disclaimer.\n2. Redistributions in binary form must reproduce the above copyright\n   notice, this list of conditions and the following disclaimer in the\n   documentation and/or other materials provided with the distribution.\n3. The name of the author may not be used to endorse or promote products\n   derived from this software without specific prior written permission.\n\nTHIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR\nIMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.\nIN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,\nINCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT\nNOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,\nDATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY\nTHEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT\n(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF\nTHIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.\n\n\n\nThe bcrypt_pbkdf portions are under the following license:\n\nCopyright (c) 2013 Ted Unangst <tedu@openbsd.org>\n\nPermission to use, copy, modify, and distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n\n\nPerformance improvements (Javascript-specific):\n\nCopyright 2016, Joyent Inc\nAuthor: Alex Wilson <alex.wilson@joyent.com>\n\nPermission to use, copy, modify, and distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF\nOR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - lru-cache@7.18.3\n\nThis package contains the following license:\n\nThe ISC License\n\nCopyright (c) 2010-2023 Isaac Z. Schlueter and Contributors\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR\nIN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - graceful-fs@4.2.11\n\nThis package contains the following license:\n\nThe ISC License\n\nCopyright (c) 2011-2022 Isaac Z. Schlueter, Ben Noordhuis, and Contributors\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR\nIN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - minimatch@5.1.9\n - minimatch@9.0.9\n\nThese packages each contain the following license:\n\nThe ISC License\n\nCopyright (c) 2011-2023 Isaac Z. Schlueter and Contributors\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR\nIN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - signal-exit@4.1.0\n\nThis package contains the following license:\n\nThe ISC License\n\nCopyright (c) 2015-2023 Benjamin Coe, Isaac Z. Schlueter, and Contributors\n\nPermission to use, copy, modify, and/or distribute this software\nfor any purpose with or without fee is hereby granted, provided\nthat the above copyright notice and this permission notice\nappear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE\nLIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES\nOR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\nWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\nARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - glob-parent@5.1.2\n\nThis package contains the following license:\n\nThe ISC License\n\nCopyright (c) 2015, 2019 Elan Shanker\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR\nIN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - signal-exit@3.0.7\n\nThis package contains the following license:\n\nThe ISC License\n\nCopyright (c) 2015, Contributors\n\nPermission to use, copy, modify, and/or distribute this software\nfor any purpose with or without fee is hereby granted, provided\nthat the above copyright notice and this permission notice\nappear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES\nOF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE\nLIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES\nOR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,\nWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,\nARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - inflight@1.0.6\n\nThis package contains the following license:\n\nThe ISC License\n\nCopyright (c) Isaac Z. Schlueter\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR\nIN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - inherits@2.0.4\n\nThis package contains the following license:\n\nThe ISC License\n\nCopyright (c) Isaac Z. Schlueter\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - chownr@1.1.4\n - ini@1.3.8\n - isexe@2.0.0\n - json-stringify-safe@5.0.1\n - minimatch@3.1.5\n - mute-stream@0.0.8\n - mute-stream@2.0.0\n - once@1.4.0\n - semver@7.7.3\n - which@2.0.2\n - wrappy@1.0.2\n\nThese packages each contain the following license:\n\nThe ISC License\n\nCopyright (c) Isaac Z. Schlueter and Contributors\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR\nIN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - fs.realpath@1.0.0\n\nThis package contains the following license:\n\nThe ISC License\n\nCopyright (c) Isaac Z. Schlueter and Contributors\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR\nIN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n----\n\nThis library bundles a version of the `fs.realpath` and `fs.realpathSync`\nmethods from Node.js v0.10 under the terms of the Node.js MIT license.\n\nNode's license follows, also included at the header of `old.js` which contains\nthe licensed code:\n\n  Copyright Joyent, Inc. and other Node contributors.\n\n  Permission is hereby granted, free of charge, to any person obtaining a\n  copy of this software and associated documentation files (the \"Software\"),\n  to deal in the Software without restriction, including without limitation\n  the rights to use, copy, modify, merge, publish, distribute, sublicense,\n  and/or sell copies of the Software, and to permit persons to whom the\n  Software is furnished to do so, subject to the following conditions:\n\n  The above copyright notice and this permission notice shall be included in\n  all copies or substantial portions of the Software.\n\n  THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER\n  DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - glob@7.2.3\n\nThis package contains the following license:\n\nThe ISC License\n\nCopyright (c) Isaac Z. Schlueter and Contributors\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES\nWITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF\nMERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR\nANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES\nWHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN\nACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR\nIN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n## Glob Logo\n\nGlob's logo created by Tanya Brassie <http://tanyabrassie.com/>, licensed\nunder a Creative Commons Attribution-ShareAlike 4.0 International License\nhttps://creativecommons.org/licenses/by-sa/4.0/\n\n-----------\n\nThe following npm package may be included in this product:\n\n - at-least-node@1.0.0\n\nThis package contains the following license:\n\nThe ISC License\nCopyright (c) 2020 Ryan Zimmerman <opensrc@ryanzim.com>\n\nPermission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - @octokit/rest@22.0.1\n\nThis package contains the following license:\n\nThe MIT License\n\nCopyright (c) 2012 Cloud9 IDE, Inc. (Mike de Boer)\nCopyright (c) 2017-2018 Octokit contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - buffer-crc32@0.2.13\n\nThis package contains the following license:\n\nThe MIT License\n\nCopyright (c) 2013 Brian J. Brennan\n\nPermission is hereby granted, free of charge, to any person obtaining a copy \nof this software and associated documentation files (the \"Software\"), to deal in \nthe Software without restriction, including without limitation the rights to use, \ncopy, modify, merge, publish, distribute, sublicense, and/or sell copies of the \nSoftware, and to permit persons to whom the Software is furnished to do so, \nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all \ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, \nINCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR \nPURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE\nFOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - proxy-from-env@1.1.0\n\nThis package contains the following license:\n\nThe MIT License\n\nCopyright (C) 2016-2018 Rob Wu <rob@robwu.nl>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - @octokit/endpoint@11.0.2\n - @octokit/graphql@9.0.3\n - @octokit/request@10.0.7\n\nThese packages each contain the following license:\n\nThe MIT License\n\nCopyright (c) 2018 Octokit contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - @octokit/auth-token@6.0.0\n - @octokit/request-error@7.1.0\n\nThese packages each contain the following license:\n\nThe MIT License\n\nCopyright (c) 2019 Octokit contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - csv-parse@6.1.0\n - csv@6.4.1\n - stream-transform@3.4.0\n\nThese packages each contain the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2010 Adaltas\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - mime@1.6.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2010 Benjamin Thomas, Robert Kieffer\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - uuid@8.3.2\n - uuid@9.0.1\n\nThese packages each contain the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2010-2020 Robert Kieffer and other contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - socks@2.8.7\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2013 Josh Glazebrook\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - raw-body@2.5.3\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2013-2014 Jonathan Ong <me@jongleberry.com>\nCopyright (c) 2014-2022 Douglas Christopher Wilson <doug@somethingdoug.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - utils-merge@1.0.1\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2013-2017 Jared Hanson\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - smart-buffer@4.2.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2013-2017 Josh Glazebrook\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - bluebird@3.7.2\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2013-2018 Petka Antonov\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - deep-extend@0.6.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2013-2018, Viacheslav Lotsmanov\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - array-flatten@1.1.1\n - path-to-regexp@0.1.12\n - ts-node@10.9.2\n\nThese packages each contain the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Blake Embrey (hello@blakeembrey.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - @cspotcode/source-map-support@0.8.1\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Evan Wallace\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - base64-js@1.5.1\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Jameson Little\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - ecc-jsbn@0.1.2\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Jeremie Miller\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - end-of-stream@1.4.5\n - pump@3.0.3\n - tar-fs@2.1.4\n - tar-stream@2.2.0\n\nThese packages each contain the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Mathias Buus\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - object-hash@3.0.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 object-hash contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - run-async@2.4.1\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Simon Boudrias\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - extend@3.0.2\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014 Stefan Thomas\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - is-extglob@2.1.1\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014-2016, Jon Schlinkert\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - is-glob@4.0.3\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014-2017, Jon Schlinkert.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - normalize-path@3.0.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014-2018, Jon Schlinkert.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - merge2@1.4.1\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014-2020 Teambition\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - braces@3.0.3\n - fill-range@7.1.1\n - is-number@7.0.0\n - micromatch@4.0.8\n\nThese packages each contain the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014-present, Jon Schlinkert.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - js-tokens@4.0.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2014, 2015, 2016, 2017, 2018 Simon Lydell\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - loose-envify@1.4.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2015 Andres Suarez <zertosh@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - error-ex@1.3.4\n - is-arrayish@0.2.1\n\nThese packages each contain the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2015 JD Ballard\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - prebuild-install@7.1.3\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2015 Mathias Buus\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - ajv@6.14.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2015-2017 Evgeny Poberezkin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - reusify@1.1.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2015-2024 Matteo Collina\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - to-regex-range@5.0.1\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2015-present, Jon Schlinkert.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - whatwg-url@5.0.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2015–2016 Sebastian Mayr\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - asynckit@0.4.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2016 Alex Indigo\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - node-fetch@2.7.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2016 David Frank\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - ms@2.0.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2016 Zeit, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - stack-utils@2.0.6\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2016-2022 Isaac Z. Schlueter <i@izs.me>, James Talmage <james@talmage.io> (github.com/jamestalmage), and Contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - picomatch@2.3.1\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2017-present, Jon Schlinkert.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - natural-orderby@2.0.3\n - natural-orderby@3.0.2\n\nThese packages each contain the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2018 - present Olaf Ennen\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - jose@5.10.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2018 Filip Skokan\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - expand-template@2.0.3\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2018 Lars-Magnus Skog\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - cross-spawn@7.0.6\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2018 Made With MOXY Lda <hello@moxy.studio>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - fs-constants@1.0.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2018 Mathias Buus\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - v8-compile-cache-lib@3.0.1\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2019 Andres Suarez\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - mkdirp-classic@0.5.3\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2020 James Halliday (mail@substack.net) and Mathias Buus\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - ms@2.1.3\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2020 Vercel, Inc.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - defaults@1.0.4\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) 2022 Sindre Sorhus\nCopyright (c) 2015 Elijah Insua\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - @nodelib/fs.scandir@2.1.5\n - @nodelib/fs.stat@2.0.5\n - @nodelib/fs.walk@1.2.8\n - fast-glob@3.3.3\n\nThese packages each contain the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) Denis Malinochkin\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - safe-buffer@5.1.2\n - safe-buffer@5.2.1\n\nThese packages each contain the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) Feross Aboukhadijeh\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - queue-microtask@1.2.3\n - run-parallel@1.2.0\n - simple-concat@1.0.1\n - simple-get@4.0.1\n\nThese packages each contain the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) Feross Aboukhadijeh\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - buffer@5.7.1\n - buffer@6.0.3\n\nThese packages each contain the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) Feross Aboukhadijeh, and other contributors.\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - merge-options@3.0.4\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) Michael Mayer <michael@schnittstabil.de>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - escape-string-regexp@1.0.5\n - is-fullwidth-code-point@2.0.0\n - p-finally@1.0.0\n - path-is-absolute@1.0.1\n - strip-json-comments@2.0.1\n\nThese packages each contain the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) Sindre Sorhus <sindresorhus@gmail.com> (sindresorhus.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - code-excerpt@4.0.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) Vadim Demedes <vdemedes@gmail.com> (github.com/vadimdemedes)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - convert-to-spaces@2.0.1\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) Vadim Demedes <vdemedes@gmail.com> (https://vadimdemedes.com)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - is-retry-allowed@1.2.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright (c) Vsevolod Strukchinsky <floatdrop@gmail.com> (github.com/floatdrop)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - crc@3.8.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright 2014 Alex Gorbatchev\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - nanoid@3.3.11\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n\nCopyright 2017 Andrey Sitnik <andrey@sitnik.ru>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - jsonwebtoken@9.0.3\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n \nCopyright (c) 2015 Auth0, Inc. <support@auth0.com> (http://auth0.com)\n \nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n \nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n \nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - bl@4.1.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n=====================\n\nCopyright (c) 2013-2019 bl contributors\n----------------------------------\n\n*bl contributors listed at <https://github.com/rvagg/bl#contributors>*\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - isstream@0.1.2\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n=====================\n\nCopyright (c) 2015 Rod Vagg\n---------------------------\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - node-addon-api@4.3.0\n\nThis package contains the following license:\n\nThe MIT License (MIT)\n=====================\n\nCopyright (c) 2017 Node.js API collaborators\n-----------------------------------\n\n*Node.js API collaborators listed at <https://github.com/nodejs/node-addon-api#collaborators>*\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - color-name@1.1.3\n - color-name@1.1.4\n\nThese packages each contain the following license:\n\nThe MIT License (MIT)\nCopyright (c) 2015 Dmitry Ivanov\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - cli-progress@2.1.1\n\nThis package contains the following license:\n\nThe MIT License (X11 License)\n\nCopyright (c) 2015-2018 Andi Dittrich\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - cli-progress@3.12.0\n\nThis package contains the following license:\n\nThe MIT License (X11 License)\n\nCopyright (c) 2015-2022 Andi Dittrich\n\nPermission is hereby granted, free of charge, to any person\nobtaining a copy of this software and associated documentation\nfiles (the \"Software\"), to deal in the Software without\nrestriction, including without limitation the rights to use,\ncopy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the\nSoftware is furnished to do so, subject to the following\nconditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES\nOF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT\nHOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\nFROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - tweetnacl@0.14.5\n\nThis package contains the following license:\n\nThis is free and unencumbered software released into the public domain.\n\nAnyone is free to copy, modify, publish, use, compile, sell, or\ndistribute this software, either in source code form or as a compiled\nbinary, for any purpose, commercial or non-commercial, and by any\nmeans.\n\nIn jurisdictions that recognize copyright laws, the author or authors\nof this software dedicate any and all copyright interest in the\nsoftware to the public domain. We make this dedication for the benefit\nof the public at large and to the detriment of our heirs and\nsuccessors. We intend this dedication to be an overt act of\nrelinquishment in perpetuity of all present and future rights to this\nsoftware under copyright law.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.\nIN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR\nOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,\nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR\nOTHER DEALINGS IN THE SOFTWARE.\n\nFor more information, please refer to <http://unlicense.org>\n\n-----------\n\nThe following npm package may be included in this product:\n\n - fast-json-stable-stringify@2.1.0\n\nThis package contains the following license:\n\nThis software is released under the MIT license:\n\nCopyright (c) 2017 Evgeny Poberezkin\nCopyright (c) 2013 James Halliday\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm packages may be included in this product:\n\n - concat-map@0.0.1\n - github-from-package@0.0.0\n - is-typedarray@1.0.0\n - minimist@1.2.8\n - wordwrap@1.0.0\n\nThese packages each contain the following license:\n\nThis software is released under the MIT license:\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n-----------\n\nThe following npm package may be included in this product:\n\n - wcwidth@1.0.1\n\nThis package contains the following license:\n\nwcwidth.js: JavaScript Portng of Markus Kuhn's wcwidth() Implementation\n=======================================================================\n\nCopyright (C) 2012 by Jun Woong.\n\nThis package is a JavaScript porting of `wcwidth()` implementation\n[by Markus Kuhn](http://www.cl.cam.ac.uk/~mgk25/ucs/wcwidth.c).\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\nof the Software, and to permit persons to whom the Software is furnished to do\nso, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\n\nTHIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,\nINCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND\nFITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR\nOR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,\nEXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,\nPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR\nBUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER\nIN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\nARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE\nPOSSIBILITY OF SUCH DAMAGE.\n\n-----------\n\nThis file was generated with the generate-license-file npm package!\nhttps://www.npmjs.com/package/generate-license-file\n"
  },
  {
    "path": "README.md",
    "content": "<p align=\"center\">\n  <img src=\"https://github.com/box/sdks/blob/master/images/box-dev-logo.png\" alt= “box-dev-logo” width=\"30%\" height=\"50%\">\n</p>\n\n# Box CLI\n\n[![Project Status](http://opensource.box.com/badges/active.svg)](http://opensource.box.com/badges)\n![Platform](https://img.shields.io/badge/node-18--22-blue)\n[![Coverage](https://coveralls.io/repos/github/box/boxcli/badge.svg?branch=main)](https://coveralls.io/github/box/boxcli?branch=main)\n\nThe Box CLI is a user-friendly command line tool which allows both technical and non-technical users to leverage the Box API to perform routine or bulk actions. There is no need to write any code, as these actions are executed through a [set of commands](#command-topics).\n\nAmong other features, Box CLI includes the following functionality:\n* [Bulk actions](docs/Bulk%20actions/README.md) - A csv file can be used to execute commands in bulk, and each row of the spreadsheet is treated as an individual API call.\n* As-User header - Act on behalf of another user.\n* Search API - Search for files and folders in your Box Enterprise account.\n\n## Table of contents\n\n<!-- START doctoc generated TOC please keep comment here to allow auto update -->\n<!-- DON'T EDIT THIS SECTION, INSTEAD RE-RUN doctoc TO UPDATE -->\n\n  - [Getting Started](#getting-started)\n    - [CLI Installation](#cli-installation)\n      - [Windows & macOS Installers](#windows--macos-installers)\n      - [Linux & Node install](#linux--node-install)\n    - [Quick Login with the Official Box CLI App](#quick-login-with-the-official-box-cli-app)\n    - [CLI and Server Authentication with JWT](#cli-and-server-authentication-with-jwt)\n    - [Logout](#logout)\n  - [Secure Storage](#secure-storage)\n    - [What is Stored Securely](#what-is-stored-securely)\n    - [Platform Support](#platform-support)\n    - [Linux Installation](#linux-installation)\n    - [Automatic Migration](#automatic-migration)\n    - [Data Location](#data-location)\n  - [Usage](#usage)\n- [Command Topics](#command-topics)\n  - [Questions, Bugs, and Feature Requests?](#questions-bugs-and-feature-requests)\n  - [Versions](#versions)\n    - [Supported Version](#supported-version)\n    - [Version schedule](#version-schedule)\n  - [Contributing to the Box CLI](#contributing-to-the-box-cli)\n  - [Copyright and License](#copyright-and-license)\n\n<!-- END doctoc generated TOC please keep comment here to allow auto update -->\n\n## Getting Started\n\n### CLI Installation\nInstallers are available for Windows and macOS. However, the raw source-code is available if you would like to build the CLI in other environments.\n\n#### Windows & macOS Installers\nTo install the latest CLI on your machine, download the latest `.exe` for Windows or `.pkg` for macOS for the [latest release](https://github.com/box/boxcli/releases).\n\n#### Linux & Node install\nAdditionally, the CLI can be installed as a Node package on any platform, including Linux. For this to work, you will need to have [Node JS](https://nodejs.org/) installed on your machine.\n\n```bash\nnpm install --global @box/cli\n```\n\n### Quick Login with the Official Box CLI App\n\nAfter installation, run `box login` to sign in. You will be prompted with three options:\n\n- **[1] Official Box CLI App** — No app setup required. Uses predefined scopes limited to content actions.\n- **[2] Your own Platform OAuth app** — Enter your Client ID and Client Secret for custom scopes or specific configuration.\n- **[q] Quit** — Exit the login flow.\n\nYou can also paste a Client ID directly at the prompt (any input between 16 and 99 characters is recognized as a Client ID).\n\n**Quick start** — skip the prompt and go directly to authorization with the Official Box CLI App:\n\n```bash\nbox login -d\n```\n\nA browser window opens for authorization. Once you grant access, the CLI creates a new environment and you're ready to go. See the [authentication docs](docs/authentication.md) for more details.\n\n**Platform App** — run `box login`, choose `[2]`, and enter your credentials from the [Box Developer Console][dev-console]. See the [Box CLI with OAuth 2.0 guide][oauth-guide] and the [authentication docs](docs/authentication.md) for setup instructions.\n\n### CLI and Server Authentication with JWT\n\nAlternatively, to get started with the Box CLI, [download and install](#CLI-Installation) CLI, set up a Box application using Server Authentication with JWT and\ndownload the JSON configuration file from the Configuration page of your Platform App in the\n[Box Developer Console][dev-console] following [JWT CLI Guide][jwt-guide].  Then, set up the CLI by pointing it to your configuration file:\n\n```sh-session\n$ box configure:environments:add PATH_TO_CONFIG_FILE\nSuccessfully added CLI environment \"default\"\n```\n\nIf you manually generated your own private key to use with JWT authentication, you will need to point the CLI to the\nlocation of your private key file:\n\n```sh-session\n$ box configure:environments:add PATH_TO_CONFIG_FILE --private-key-path PATH_TO_PRIVATE_KEY --name ManualKey\nSuccessfully added CLI environment \"ManualKey\"\n```\n\n[dev-console]: https://app.box.com/developers/console\n[oauth-guide]: https://developer.box.com/guides/cli/quick-start/\n[jwt-guide]: https://developer.box.com/guides/cli/cli-docs/jwt-cli/\n\n### Logout\n\nTo sign out from the current environment, run:\n\n```bash\nbox logout\n```\n\nThis revokes the access token on Box and clears the local token cache. For OAuth, run `box login` to authorize again. For CCG and JWT, a new token is fetched automatically on the next command. Use `-f` to skip the confirmation prompt, or `--on-revoke-failure=clear` / `--on-revoke-failure=abort` to control behavior when token revocation fails. See [`box logout`](docs/logout.md) for full details.\n\n## Secure Storage\n\nThe Box CLI uses secure storage to protect your sensitive data:\n\n### What is Stored Securely\n\n- **Environment Configuration**: Client IDs, client secrets, and enterprise IDs, private keys and public keys\n- **Authentication Tokens**: Access tokens and refresh tokens for all configured environments\n\n### Platform Support\n\n| Platform | Secure Storage | Installation Required |\n|----------|---------------|----------------------|\n| **macOS** | Keychain | Built-in |\n| **Windows** | Credential Manager | Built-in |\n| **Linux** | Secret Service (libsecret) | May require installation |\n\n### Linux Installation\n\nOn Linux systems, you need to install `libsecret-1-dev` for secure storage.\n\n**Note**: If libsecret is not installed, the CLI will automatically fall back to storing credentials in plain text files in `~/.box/`. You can still use the CLI, but for security, we recommend installing libsecret.\n\n### Automatic Migration\n\nWhen you upgrade to a version with secure storage support:\n- Existing plaintext credentials are automatically read\n- On the next token refresh or configuration update, credentials are migrated to secure storage\n- Old plaintext files are automatically deleted after successful migration\n- No manual action required!\n\n### Data Location\n\n- **Secure Storage**: Credentials stored in your OS keychain/credential manager\n- **Fallback (if secure storage unavailable)**: `~/.box/box_environments.json` and `~/.box/{environment}_token_cache.json`\n\n## Usage\n\n```sh-session\n$ box --version\nbox-cli/0.0.0 darwin-x64 node-v10.10.0\n$ box users:get --help\nGet information about a Box user\n\nUSAGE\n  $ box users:get [ID]\n\nARGUMENTS\n  ID  [default: me] ID of the user to get; defaults to the current user\n\nOPTIONS\n  -h, --help                             Show CLI help\n  -s, --save                             Save report to default reports folder on disk\n  -t, --token=token                      Provide a token to perform this call\n  -v, --verbose                          Show verbose output, which can be helpful for debugging\n  -y, --yes                              Automatically respond yes to all confirmation prompts\n  --as-user=as-user                      Provide an ID for a user\n  --bulk-file-path=bulk-file-path        File path to bulk .csv or .json objects\n  --csv                                  Output formatted CSV\n  --fields=fields                        Comma separated list of fields to show\n  --json                                 Output formatted JSON\n  --no-color                             Turn off colors for logging\n  --save-to-file-path=save-to-file-path  Override default file path to save report\n$ box users:get\nType: user\nID: '77777'\nName: Example User\nLogin: user@example.com\nCreated At: '2016-12-07T17:30:40-08:00'\nModified At: '2018-11-15T17:33:06-08:00'\nLanguage: en\nTimezone: America/Los_Angeles\nSpace Amount: 10737418240\nSpace Used: 53569393\nMax Upload Size: 5368709120\nStatus: active\nJob Title: ''\nPhone: ''\nAddress: ''\nAvatar URL: 'https://app.box.com/api/avatar/large/77777'\n```\n\n\n<!-- commands -->\n# Command Topics\n\n* [`box ai`](docs/ai.md) - Sends a request to supported LLMs using Box AI. This is intended for direct use, not by AI agents.\n* [`box autocomplete`](docs/autocomplete.md) - Display autocomplete installation instructions\n* [`box collaboration-allowlist`](docs/collaboration-allowlist.md) - List collaboration allowlist entries\n* [`box collaborations`](docs/collaborations.md) - Manage collaborations\n* [`box collections`](docs/collections.md) - List your collections\n* [`box comments`](docs/comments.md) - Manage comments on files\n* [`box configure`](docs/configure.md) - Configure the Box CLI\n* [`box device-pins`](docs/device-pins.md) - List all the device pins for your enterprise\n* [`box events`](docs/events.md) - Get events\n* [`box file-requests`](docs/file-requests.md) - Copies existing file request to new folder\n* [`box files`](docs/files.md) - Manage files\n* [`box folders`](docs/folders.md) - Manage folders\n* [`box groups`](docs/groups.md) - List all groups\n* [`box help`](docs/help.md) - Display help for the Box CLI\n* [`box hubs`](docs/hubs.md) - List Box Hubs for the current user\n* [`box integration-mappings`](docs/integration-mappings.md) - List Slack integration mappings\n* [`box legal-hold-policies`](docs/legal-hold-policies.md) - List legal hold policies\n* [`box login`](docs/login.md) - Sign in with OAuth 2.0 and create a new environment (or update an existing one with --reauthorize).\n* [`box logout`](docs/logout.md) - Revoke the access token and clear local token cache.\n* [`box metadata-cascade-policies`](docs/metadata-cascade-policies.md) - List the metadata cascade policies on a folder\n* [`box metadata-query`](docs/metadata-query.md) - Create a search using SQL-like syntax to return items that match specific metadata\n* [`box metadata-templates`](docs/metadata-templates.md) - Get all metadata templates in your Enterprise\n* [`box oss`](docs/oss.md) - Print a list of open-source licensed packages used in the Box CLI\n* [`box recent-items`](docs/recent-items.md) - List information about files accessed in the past 90 days up to a 1000 items\n* [`box request`](docs/request.md) - Manually specify a Box API request\n* [`box retention-policies`](docs/retention-policies.md) - List all retention policies for your enterprise\n* [`box search`](docs/search.md) - Search for files and folders in your Enterprise\n* [`box shared-links`](docs/shared-links.md) - Manage shared links\n* [`box sign-requests`](docs/sign-requests.md) - List sign requests\n* [`box sign-templates`](docs/sign-templates.md) - List sign templates\n* [`box storage-policies`](docs/storage-policies.md) - List storage policies\n* [`box tasks`](docs/tasks.md) - Manage tasks\n* [`box terms-of-service`](docs/terms-of-service.md) - List terms of services for your enterprise\n* [`box tokens`](docs/tokens.md) - Get a token. Returns the service account token by default\n* [`box trash`](docs/trash.md) - List all items in trash\n* [`box update`](docs/update.md) - Update the BoxCLI using GitHub\n* [`box users`](docs/users.md) - List all Box users\n* [`box version`](docs/version.md)\n* [`box watermarking`](docs/watermarking.md) - Apply a watermark on an item\n* [`box web-links`](docs/web-links.md) - Manage web links\n* [`box webhooks`](docs/webhooks.md) - List all webhooks\n\n<!-- commandsstop -->\n\n## Questions, Bugs, and Feature Requests?\n\n[Browse the issues tickets](https://github.com/box/boxcli/issues)! Or, if that doesn't work, [file a new one](https://github.com/box/boxcli/issues/new) and someone will get back to you.   If you have general questions about the\nBox API, you can post to the [Box Developer Forum](https://community.box.com/t5/Developer-Forum/bd-p/DeveloperForum).\n\n\n## Versions\n\nWe use a modified version of [Semantic Versioning](https://semver.org/) for all changes. See [version strategy](VERSIONS.md) for details which is effective from 30 July 2022.\n\n### Supported Version\n\nOnly the current MAJOR version of SDK is supported. New features, functionality, bug fixes, and security updates will only be added to the current MAJOR version.\n\nA current release is on the leading edge of our SDK development, and is intended for customers who are in active development and want the latest and greatest features.  Instead of stating a release date for a new feature, we set a fixed minor or patch release cadence of maximum 2-3 months (while we may release more often). At the same time, there is no schedule for major or breaking release. Instead, we will communicate one quarter in advance the upcoming breaking change to allow customers to plan for the upgrade. We always recommend that all users run the latest available minor release for whatever major version is in use. We highly recommend upgrading to the latest SDK major release at the earliest convenient time and before the EOL date.\n\n### Version schedule\n\n| Version | Supported Environments  | State     | First Release | EOL/Terminated |\n|---------|-------------------------|-----------|---------------|----------------|\n| 4       | Node.js >= 18           |           |               |                |\n| 3       | Node.js >= 16           | Supported | 01 Feb 2022   | TBD            |\n| 2       |                         | EOL       | 14 Dec 2018   | 01 Feb 2022    |\n| 1       |                         | EOL       | 01 Nov 2017   | 14 Dec 2018    |\n\n## Contributing to the Box CLI\n\n1. Clone this repo.\n1. Run `npm install`.\n1. Run `npm test` to ensure everything is working.\n1. Make the changes you want in the `src/` directory.  Be sure to add corresponding tests\nin the `test/` directory!\n1. Create a pull request with your changes — we'll review it and help you get it merged.\n\nFor more information, please see [the Contribution guidelines](./CONTRIBUTING.md).\n\n## Copyright and License\n\nCopyright 2018 Box, Inc. All rights reserved.\n\nLicensed under the Apache License, Version 2.0 (the \"License\");\nyou may not use this file except in compliance with the License.\nYou may obtain a copy of the License at\n\n   http://www.apache.org/licenses/LICENSE-2.0\n\nUnless required by applicable law or agreed to in writing, software\ndistributed under the License is distributed on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\nSee the License for the specific language governing permissions and\nlimitations under the License.\n\nThis software includes third party libraries, which are distributed under their own licenses' terms;\nsee [LICENSE-THIRD-PARTY.txt](./LICENSE-THIRD-PARTY.txt) for details.\n"
  },
  {
    "path": "UPGRADE.md",
    "content": "# Upgrade\n\n## Version 3.5.0 to 3.6.0\n\nMake sure you are on the latest version 3.5.0.\nIn version 3.6.0, we introduced a change in response in theese following command:\n\n- `box files:share`\n- `box files:shared-links:create`\n- `box files:shared-links:update`\n- `box folders:share`\n- `box folders:shared-links:create`\n- `box folders:shared-links:update`\n- `box shared-links:create`\n\nThe response will now return a `file` or `folder` object with `shared_link` property instead of a `shared_link` object.\n\n**Before:**\n```json\n{\n    \"url\": \"https://blosserdemoaccount.box.com/s/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p\",\n    \"download_url\": \"https://blosserdemoaccount.box.com/shared/static/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p.png\",\n    \"vanity_url\": null,\n    \"effective_access\": \"open\",\n    \"is_password_enabled\": true,\n    \"unshared_at\": null,\n    \"download_count\": 0,\n    \"preview_count\": 0,\n    \"access\": \"test\",\n    \"permissions\": {\n        \"can_download\": true,\n        \"can_preview\": true,\n        \"can_edit\": true\n    }\n}\n```\n\n**After:**\n```json \n{\n    \"type\": \"file\",\n    \"id\": \"1234567890\",\n    \"shared_link\": {\n        \"url\": \"https://blosserdemoaccount.box.com/s/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p\",\n        \"download_url\": \"https://blosserdemoaccount.box.com/shared/static/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p.png\",\n        \"vanity_url\": null,\n        \"effective_access\": \"open\",\n        \"is_password_enabled\": true,\n        \"unshared_at\": null,\n        \"download_count\": 0,\n        \"preview_count\": 0,\n        \"access\": \"test\",\n        \"permissions\": {\n            \"can_download\": true,\n            \"can_preview\": true,\n            \"can_edit\": true\n        }\n    }\n}\n```\n\nPlease check if you are using any of the commands above, then update the usage to avoid any breaks."
  },
  {
    "path": "VERSIONS.md",
    "content": "# Version Lifecycle\nWe use a modified version of [Semantic Versioning](https://semver.org/) for all changes. It is strongly encouraged that you pin at least the major version and potentially the minor version to avoid pulling in breaking changes.  Increasing the major version of an SDK indicates that this SDK underwent significant and substantial changes to support new idioms and patterns in the language. Major versions are introduced when public interfaces (e.g. classes, methods, types, etc.), behaviours, or semantics have changed. \n\nSemantic Versions take the form of `MAJOR.MINOR.PATCH`.\n\nWhen bugs are fixed in the library in a backwards-compatible way, the PATCH level will be incremented by one. PATCH changes should not break your code and are generally safe for upgrade.\n\nWhen a new feature set comes online or a small breaking change is introduced, the MINOR version will be incremented by one and the PATCH version resets to zero. MINOR changes may require some amount of manual code change for upgrade. These backwards-incompatible changes will mostly be limited to a small number of function signature changes.\n\nThe MAJOR version is used to indicate the family of technology represented by the library. Breaking changes that require extensive reworking of code will cause the MAJOR version to be incremented by one, and the MINOR and PATCH versions will be reset to zero. Since frequent major updates can be very disruptive, we will only introduce this type of breaking change when absolutely necessary.\n\nNew MAJOR versions will be communicated in advance via:\n\n* An email announcement is sent to affected accounts, announcing our plans to end support for the specific SDK version. The email will outline the path to end-of-support, specify the campaign timelines, and provide upgrade guidance.\n* Box SDK documentation, such as API reference documentation, user guides, SDK product marketing pages, and GitHub readme(s) are updated to indicate the campaign timeline and provide guidance on upgrading affected applications.\n* Deprecation warnings are added to the SDKs, outlining the path to end-of-support and linking to the SDK documentation.\n\nDeprecations are introduced in minor releases. We will not introduce new deprecations in patch releases. These deprecations will preserve the existing behaviour while emitting a warning that provide guidance on:\n\n* How to achieve similar behaviour if an alternative is available\n* The version in which the deprecation will be enforced.\n\nDeprecations will only be enforced in major releases. For example, if a behaviour is deprecated in version 1.2.0, it will continue to work, with a warning, for all releases in the 1.x series. The behaviour will change and the deprecation will be removed in the next major release (2.x.x)."
  },
  {
    "path": "bin/run",
    "content": "#!/usr/bin/env node\n\nconst { handle } = require('@oclif/core/errors');\nconst flush = require('@oclif/core/flush');\n\nrequire('@oclif/core').run()\n.then(flush)\n.catch(handle);\n"
  },
  {
    "path": "bin/run.cmd",
    "content": "@echo off\n\nnode \"%~dp0\\run\" %*\n"
  },
  {
    "path": "docs/Bulk actions/README.md",
    "content": "# Box CLI Bulk commands\n\nThe Box CLI provides a key element to Box's APIs with bulk operations, with the ability to support repetitive tasks in a single command with a local CSV file.\n\n## Table of contents\n\n- [Getting Started](#getting-started)\n- [Available CSV Templates](#available-csv-templates)\n\n\n## Getting Started\n\nFor most operations listed in our documentation, getting started is as easy as flagging the command with `--bulk-file-path` and supplying the CSV file path.\n\n```bash\nbox files:download --bulk-file-path path/to/csv/file.csv --destination path/to/destination/folder\n```\n\n### Setup\n1. Clone this github repo or download files from the [`/docs/Bulk actions`][csv-template] directory\n    ```bash\n    git clone https://github.com/box/boxcli.git\n    ```\n2. Create an OAuth Application following the [CLI Setup Quick Start][oauth-guide].\n3. Navigate to a particular [CSV template][csv-template] in the and adjust it based on your data.\n\n\n\n## Available CSV Templates\n\n* [`box collaborations`](collaborations/collaborations.md) - Manage collaborations\n* [`box files`](files/files.md) - Manage files\n* [`box folders`](folders/folders.md) - Manage folders\n* [`box groups`](groups/groups.md) - List all groups\n* [`box metadata-templates`](metadata-templates/metadata-templates.md) - Get all metadata templates in your Enterprise\n* [`box shared-links`](shared-links/shared-links.md) - Manage shared links\n* [`box users`](users/users.md) - List all Box users\n* [`box webhooks`](webhooks/webhooks.md) - List all webhooks\n\n\n[oauth-guide]: https://developer.box.com/guides/cli/quick-start/\n[csv-template]: https://github.com/box/boxcli/tree/main/docs/Bulk%20Actions\n"
  },
  {
    "path": "docs/Bulk actions/collaborations/collaborations-add.csv",
    "content": "ITEMID,ITEMTYPE,role,login,user-id,group-id\r\n1357902468,folder,editor,externaluserA@email.com,,\r\n1357902468,folder,editor,externaluserB@email.com,,\r\n1357902468,folder,editor,externaluserC@email.com,,\r\n2468135790,file,previewer_uploader,,0987654321,\r\n2468135790,file,previewer_uploader,,7486359338,\r\n2468135790,file,previewer_uploader,,9871324987,\r\n1234567890,file,viewer,,,1234509876\r\n1234567890,file,viewer,,,8927349829\r\n1234567890,file,viewer,,,4345989273"
  },
  {
    "path": "docs/Bulk actions/collaborations/collaborations-delete.csv",
    "content": "Id,\r\n13174631181,\r\n13174704210,"
  },
  {
    "path": "docs/Bulk actions/collaborations/collaborations-update.csv",
    "content": "Id,Role,CanViewPath,Status\r\n13174631181,previewer,,accepted\r\n13174704210,editor,TRUE,"
  },
  {
    "path": "docs/Bulk actions/collaborations/collaborations.md",
    "content": "`box collaborations`\n====================\n\nManage collaborations\n\n* [`box collaborations:create ITEMID ITEMTYPE`](#box-collaborationscreate-itemid-itemtype)\n* [`box collaborations:delete ID`](#box-collaborationsdelete-id)\n* [`box collaborations:update ID`](#box-collaborationsupdate-id)\n\n## `box collaborations:create ITEMID ITEMTYPE`\n\nCollaborate users into existing files or folders\n\n```\nUSAGE\n  $ box collaborations:create ITEMID ITEMTYPE\n\nARGUMENTS\n  ITEMID    The ID of the Box item to add the collaboration to\n  ITEMTYPE  (file|folder) The type of the Box item to add the collaboration to\n  ROLE      (editor|viewer|previewer|uploader|previewer_uploader|viewer_uploader|co-owner)\n  LOGIN     Login for user to collaborate (for internal and external users)\n  USER-ID   The ID for user to collaborate\n  GROUP-ID  The ID for group to collaborate\n\nEXAMPLE\n  box collaborations:create --bulk-file-path path/to/csv/collaborations-add.csv\n```\n\n- _See documentation [collaborations.md](https://github.com/box/boxcli/blob/main/docs/collaborations.md#box-collaborationscreate-itemid-itemtype)_\n- _See example: [collaborations-add.csv](collaborations-add.csv)_\n\n## `box collaborations:delete ID`\n\nDelete collaborations based on the collaboration ID\n\n```\nUSAGE\n  $ box collaborations:delete ID\n\nARGUMENTS\n  ID        The ID of the collaboration to delete\n\nEXAMPLE\n  box collaborations:delete --bulk-file-path path/to/csv/collaborations-delete.csv\n```\n\n- _See documentation [collaborations.md](https://github.com/box/boxcli/blob/main/docs/collaborations.md#box-collaborationsdelete-id)_\n- _See example: [collaborations-delete.csv](collaborations-delete.csv)_\n\n## `box collaborations:update ID`\n\nUpdate collaborations based on the collaboration ID\n\n```\nUSAGE\n  $ box collaborations:update ID\n\nARGUMENTS\n  ID        The ID of the collaboration to update\n  ROLE      (editor|viewer|previewer|uploader|previewer_uploader|viewer_uploader|co-owner)\n  STATUS    (accepted|pending|rejected) Update the collaboration status\n\nEXAMPLE\n  box collaborations:update --bulk-file-path path/to/csv/collaborations-update.csv\n```\n\n- _See documentation [collaborations.md](https://github.com/box/boxcli/blob/main/docs/collaborations.md#box-collaborationsupdate-id)_\n- _See example: [collaborations-update.csv](collaborations-update.csv)_\n"
  },
  {
    "path": "docs/Bulk actions/files/files-download.csv",
    "content": "id\n1234567890\n2468013579\n1357924680\n1111111111\n2222222222\n3333333333\n4444444444\n5555555555\n6666666666\n7777777777\n8888888888\n9999999999"
  },
  {
    "path": "docs/Bulk actions/files/files-update.csv",
    "content": "Id,Name\r\n1357924680,\"\"\"New File Name.pdf\"\"\"\r\n2468013579,\"\"\"Newer File Name.docx\"\"\"\r\n1234560987,\"\"\"Newest File Name.csv\"\"\""
  },
  {
    "path": "docs/Bulk actions/files/files-upload.csv",
    "content": "PATH,as-user\r\n\"\\path\\to\\file\\s2s.png\",17620575501\r\n\"\\path\\to\\file\\user-objects.png\",17620573934\r\n\"\\path\\to\\file\\logo.png\",17620572507\r\n\"\\path\\to\\file\\leveraging.png\",17620025743\r\n\"\\path\\to\\file\\classic.png\",17620458248\r\n\"\\path\\to\\file\\service-account.png\",17620569993\r\n\"\\path\\to\\file\\app-user.png\",17620568937\r\n\"\\path\\to\\file\\app-user-2.png\",17619924434\r\n\"\\path\\to\\file\\classic-2.png\",17620428624\r\n\"\\path\\to\\file\\leveraging-2.png\",17620568295"
  },
  {
    "path": "docs/Bulk actions/files/files.md",
    "content": "`box files`\n===========\n\nManage files\n\n* [`box files:download ID`](#box-filesdownload-id)\n* [`box files:update ID`](#box-filesupdate-id)\n* [`box files:upload PATH`](#box-filesupload)\n\n## `box files:download ID`\n\nDownload files\n\n```\nARGUMENTS PER SEPARATED VALUE\n  ID                ID of the file to download\n\nEXAMPLE\n  box files:download --bulk-file-path path/to/csv/file.csv --destination path/to/destination/folder\n```\n- _See documentation [files.md](https://github.com/box/boxcli/blob/main/docs/files.md#box-filesdownload-id)_\n- _See example: [files-download.csv](files-download.csv)_\n\n\n## `box files:update ID`\n\nUpdate file records\n\n```\nUSAGE\n  $ box files:update ID\n\nARGUMENTS PER SEPARATED VALUE\n  ID                ID of the file to update (*required*)\n  Name              new name for each file\n  Description       new description for each file \n\n\nEXAMPLE\n  box files:update --bulk-file-path path/to/csv/file.csv\n```\n\n\n- _See documentation [files.md](https://github.com/box/boxcli/blob/main/docs/files.md#box-filesupdate-id)_\n- _See example: [files-update.csv](files-update.csv)_\n\n## `box files:upload PATH`\n\nUpload files\n\n```\nARGUMENTS PER SEPARATED VALUE\n  PATH              Path to the file to be uploaded\n\nEXAMPLE\n  box files:upload --bulk-file-path path/to/csv/file.csv\n```\n- _See documentation [files.md](https://github.com/box/boxcli/blob/main/docs/files.md#box-filesupload-path)_\n- _See example: [files-upload.csv](files-upload.csv)_\n"
  },
  {
    "path": "docs/Bulk actions/folders/folders-create.csv",
    "content": "Name,ParentId\r\nmass-creation,0\r\naddl-testing,0\r\nservice-folder,,0\r\nbasic-create,,0\r\n"
  },
  {
    "path": "docs/Bulk actions/folders/folders-metadata-add.csv",
    "content": "Id,Scope,TemplateKey,Data,Data\n34250339490,enterprise,employeeRecord,name=My name,department=Sales_1\n"
  },
  {
    "path": "docs/Bulk actions/folders/folders-update.csv",
    "content": "Id,Name,Description,SyncState,ParentId,FolderUploadEmailAccess,SharedLinkAccess,SharedLinkPassword,SharedLinkUnsharedAt,SharedLinkCanDownload\r\n34250348576,updating-name-for-meeting,Another update,,,,company,password1,,\r\n34250339490,ghosts,,,,open,,,,"
  },
  {
    "path": "docs/Bulk actions/folders/folders.md",
    "content": "`box folders`\n=============\n\nManage folders\n\n* [`box folders:create PARENTID NAME`](#box-folderscreate-parentid-name)\n* [`box folders:metadata:add ID`](#box-foldersmetadataadd-id)\n* [`box folders:update ID`](#box-foldersupdate-id)\n\n\n\n## `box folders:create PARENTID NAME`\n\nCreate a new folder\n\n```\nUSAGE\n  $ box folders:create PARENTID NAME\n\nARGUMENTS\n  PARENTID  ID of parent folder to add new folder to, use '0' for the root folder\n  NAME      Name of new folder\n\nEXAMPLE\n  box folders:create --bulk-file-path path/to/csv/folders-create.csv\n```\n\n- _See documentation [folders.md](https://github.com/box/boxcli/blob/main/docs/folders.md#box-folderscreate-parentid-name)_\n- _See example: [folders-create.csv](folders-create.csv)_\n\n\n## `box folders:metadata:add ID`\n\nAdd metadata to a folder\n\n```\nUSAGE\n  $ box folders:metadata:add ID\n\nARGUMENTS\n  ID  ID of the folder to add metadata to\n\nALIASES\n  $ box folders:metadata:create\n\nEXAMPLE\n  box folders:metadata:add --bulk-file-path path/to/csv/folders-metadata-add.csv\n```\n\n- _See documentation [folders.md](https://github.com/box/boxcli/blob/main/docs/folders.md#box-foldersmetadataadd-id)_\n- _See example: [folders-metadata-add.csv](folders-metadata-add.csv)_\n\n\n\n## `box folders:update ID`\n\nUpdate a folder\n\n```\nUSAGE\n  $ box folders:update ID\n\nARGUMENTS\n  ID  ID of the folder to update\n\n\nEXAMPLE\n  box folders:update --bulk-file-path path/to/csv/folders-update.csv\n```\n\n- _See documentation [folders.md](https://github.com/box/boxcli/blob/main/docs/folders.md#box-foldersupdate-id)_\n- _See example: [folders-update.csv](folders-update.csv)_\n"
  },
  {
    "path": "docs/Bulk actions/groups/groups-create.csv",
    "content": "NAME\r\n\"Group 1\"\r\n\"Group A\"\r\n\"Group 2\"\r\n\"Group B\"\r\n\"Group 3\"\r\n\"Group C\""
  },
  {
    "path": "docs/Bulk actions/groups/groups-memberships-add.csv",
    "content": "USERID,GROUPID,ROLE\r\n13356660169,9286982656,admin\r\n17620573934,9286982656,member\r\n17620568937,9286982656,member\r\n17620568295,9286982656,member\r\n17620025743,9286934066,admin\r\n17620428624,9286934066,member\r\n17620458248,9286934066,member\r\n14953739952,9286934066,member\r\n17619924434,9286934066,member\r\n17620569993,9286896774,admin\r\n15666526271,9286896774,member\r\n17620572507,9286896774,member\r\n17620575501,9286896774,member\r\n13314716631,9286896774,member"
  },
  {
    "path": "docs/Bulk actions/groups/groups.md",
    "content": "`box groups`\n===========\n\nManage groups\n\n* [`box groups:create NAME`](#box-groupscreate-name)\n* [`box groups:memberships:add USERID GROUPID`](#box-groupsmembershipsadd-userid-groupid)\n\n## `box groups:create NAME`\n\nCreate a group\n\n```\nUSAGE\n  $ box groups:create NAME\n\nARGUMENTS\n  NAME  Group name\n\n\nEXAMPLE\n  box groups:create --bulk-file-path path/to/csv/groups-create.csv\n```\n\n- _See documentation [groups.md](https://github.com/box/boxcli/blob/main/docs/groups.md#box-groupscreate-name)_\n- _See example: [groups-create.csv](groups-create.csv)_\n\n\n\n## `box groups:memberships:add USERID GROUPID`\n\nAdd a user to a group\n\n```\nUSAGE\n  $ box groups:memberships:add USERID GROUPID\n\nARGUMENTS\n  USERID   ID of the user to add to the group\n  GROUPID  ID of the group to add the user to\n\n\nEXAMPLE\n  box groups:memberships:add --bulk-file-path path/to/csv/groups-memberships-add.csv\n```\n\n- _See documentation [groups.md](https://github.com/box/boxcli/blob/main/docs/groups.md#box-groupsmembershipsadd-userid-groupid)_\n- _See example: [groups-memberships-add.csv](groups-memberships-add.csv)_\n"
  },
  {
    "path": "docs/Bulk actions/metadata-templates/metadata-templates-cascade.csv",
    "content": "templateKey,folder\r\nemployeeRecord,13579021\r\nemployeeRecord,24680134\r\nemployeeRecord,12345678\r\nemployeeRecord,98437635\r\nmanagerApproval,11223344\r\nmanagerApproval,55667788\r\nmanagerApproval,99112233\r\n"
  },
  {
    "path": "docs/Bulk actions/metadata-templates/metadata-templates-create.csv",
    "content": "Scope,DisplayName,Hidden,TemplateKey\r\n,CLI_NEW_TEMPLATE,,CLI_NEW_TEMPLATE\r\n,CLI_NEWER_TEMPLATE,,CLI_NEWER_TEMPLATE"
  },
  {
    "path": "docs/Bulk actions/metadata-templates/metadata-templates.md",
    "content": "`box metadata-templates`\n========================\n\nGet all metadata templates in your Enterprise\n\n* [`box metadata-templates:create`](#box-metadata-templatescreate)\n* [`box metadata-templates:cascade`](#box-metadata-templatescascade)\n\n\n## `box metadata-templates:create`\n\nCreate a new metadata template\n\n```\nUSAGE\n  $ box metadata-templates:create\n\nEXAMPLE\n  box metadata-templates:create --bulk-file-path path/to/csv/metadata-templates-create.csv\n```\n\n- _See documentation [metadata-templates.md](https://github.com/box/boxcli/blob/main/docs/metadata-templates.md#box-metadata-templatescreate)_\n- _See example: [metadata-templates-create.csv](metadata-templates-create.csv)_\n\n## `box metadata-templates:cascade TEMPLATEKEY`\n\nCreate a new metadata cascade policy on a folder\n\n```\nARGUMENTS\n  TEMPLATEKEY  The template key of the metadata template to cascade\n\nUSAGE\n  $ box metadata-templates:cascade\n\nEXAMPLE\n  box metadata-templates:cascade --bulk-file-path path/to/csv/metadata-templates-create.csv\n```\n\n- _See documentation [metadata-templates.md](https://github.com/box/boxcli/blob/main/docs/metadata-templates.md#box-metadata-templatescascade-templatekey)_\n- _See example: [metadata-templates-cascade.csv](metadata-templates-cascade.csv)_\n"
  },
  {
    "path": "docs/Bulk actions/shared-links/shared-links-delete.csv",
    "content": "itemid,itemtype\n135790246810,file\n246801357911,folder\n150234894056,file"
  },
  {
    "path": "docs/Bulk actions/shared-links/shared-links.md",
    "content": "`box shared-links`\n===========\n\nManage shared links\n\n* [`box shared-links:delete ITEMID ITEMTYPE`](#box-shared-linksdelete-itemid-itemtype)\n\n\n\n## `box shared-links:delete ITEMID ITEMTYPE`\n\nDelete a shared link for a Box item\n\n```\nUSAGE\n  $ box shared-links:delete ITEMID ITEMTYPE\n\nARGUMENTS\n  ITEMID    ID of the Box item to remove the shared link from\n  ITEMTYPE  (file|folder) Type of item for shared link: either file or folder\n\nOPTIONS\n  -h, --help                             Show CLI help\n  -q, --quiet                            Suppress any non-error output to stderr\n  -s, --save                             Save report to default reports folder on disk\n  -t, --token=token                      Provide a token to perform this call\n  -v, --verbose                          Show verbose output, which can be helpful for debugging\n  -y, --yes                              Automatically respond yes to all confirmation prompts\n  --as-user=as-user                      Provide an ID for a user\n  --bulk-file-path=bulk-file-path        File path to bulk .csv or .json objects\n  --csv                                  Output formatted CSV\n  --fields=fields                        Comma separated list of fields to show\n  --json                                 Output formatted JSON\n  --no-color                             Turn off colors for logging\n  --save-to-file-path=save-to-file-path  Override default file path to save report\n\nEXAMPLE\n  box shared-links:delete --bulk-file-path path/to/csv/shared-links-delete.csv\n```\n\n- _See documentation [shared-links.md](https://github.com/box/boxcli/blob/main/docs/shared-links.md#box-shared-linksdelete-itemid-itemtype)_\n- _See example: [shared-links/shared-links-delete.csv](shared-links-delete.csv)_\n"
  },
  {
    "path": "docs/Bulk actions/sign-requests/sign-requests-create.csv",
    "content": "signer,source-files,parent-folder\r\n\"email=userA@email.com,role=approver\",\"2468135790,2468135791\",\"1357902468\"\r\n\"email=userB@email.com,role=signer\",\"2468135799\",\"1357902460\""
  },
  {
    "path": "docs/Bulk actions/sign-requests/sign-requests.md",
    "content": "`box sign-requests`\n===========\n\nManage sign requests\n\n* [`box sign-requests:create`](#box-sign-requests:create)\n\n\n## `box sign-requests:create`\n\nCreate sign request\n\n```\nUSAGE\n  $ box sign-requests:create\n\nOPTIONS\n  -h, --help                                     Show CLI help\n  -q, --quiet                                    Suppress any non-error output to stderr\n  -s, --save                                     Save report to default reports folder on disk\n  -t, --token=token                              Provide a token to perform this call\n  -v, --verbose                                  Show verbose output, which can be helpful for debugging\n  -y, --yes                                      Automatically respond yes to all confirmation prompts\n  --as-user=as-user                              Provide an ID for a user\n  --bulk-file-path=bulk-file-path                File path to bulk .csv or .json objects\n  --csv                                          Output formatted CSV\n  --days-valid=days-valid                        Number of days after which this request will automatically expire if not completed\n  --declined-redirect-url=declined-redirect-url  The URL that a signer will be redirected to after declining to sign a document. Defining this URL overrides the default redirect URL for all signers.\n  --[no-]document-preparation-needed             Indicates if the sender should receive a `prepare_url` in the response to complete document preparation via UI.\n\n  --email-message=email-message                  Message to include in sign request email. The field is cleaned through sanitization of specific characters. However, some html tags are allowed. Links included in the message are also converted to hyperlinks in the email. The message \n                                                 may contain the following html tags including `a`, `abbr`, `acronym`, `b`, `blockquote`, `code`, `em`, `i`, `ul`, `li`, `ol`, and `strong`. Be aware that when the text to html ratio is too high, the email may end up in spam filters. \n                                                 Custom styles on these tags are not allowed. If this field is not passed, a default message will be used.\n\n  --email-subject=email-subject                  Subject of sign request email. This is cleaned by sign request. If this field is not passed, a default subject will be used.\n\n  --external-id=external-id                      This can be used to reference an ID in an external system that the sign request is related to.\n\n  --fields=fields                                Comma separated list of fields to show\n\n  --json                                         Output formatted JSON\n\n  --no-color                                     Turn off colors for logging\n\n  --parent-folder=parent-folder                  (required) The destination folder to place final, signed document and signing log\n\n  --prefill-tag=prefill-tag                      Prefills a sign related tag in the content. Pass in a comma-separated dictionary of fields: id,text,checkbox,date. Can be added multiple times.\n\n  --redirect-url=redirect-url                    The URL that a signer will be redirected to after signing a document. Defining this URL overrides the default redirect URL for all signers. If no declined redirect URL is specified, this URL will be used for decline actions as well.\n\n  --[no-]reminders-enabled                       Reminds signers to sign a document on day 3, 8, 13 and 18. Reminders are only sent to outstanding signers.\n\n  --save-to-file-path=save-to-file-path          Override default file path to save report\n\n  --signer=signer                                (required) A signer for the sign request. 35 is the max number of signers permitted. Can be added multiple times. Allowed (recommended) properties: \n                                                 email,role,is-in-person,order,embed-url-external-user-id,redirect-url,declined-redirect-url,group-id but snake case is also supported for: is_in_person,order,embed_url_external_user_id,redirect_url,declined_redirect_url,group_id\n\n  --source-files=source-files                    (required) Comma separated list of files to create a signing document from. This is currently limited to 10 files, e.g. 12345\n\n  --[no-]text-signatures-enabled                 Disables the usage of signatures generated by typing (text)\n\nEXAMPLE\n  box sign-requests:create --bulk-file-path path/to/csv/create-sign-requests.csv\n```\n\n- _See documentation [sign-requests.md](https://github.com/box/boxcli/blob/main/docs/sign-requests.md#box-sign-requestscreate)_\n- _See example: [sign-requests-create.csv](sign-requests-create.csv)_\n"
  },
  {
    "path": "docs/Bulk actions/users/create-users.csv",
    "content": "Id,Login,Name,Role,Status,Address,Phone,JobTitle,Language,MaxUploadSize,SpaceUsed,SpaceAmount,IsPlatformAccessOnly,IsSyncEnabled,IsExemptFromDeviceLimits,IsExemptFromLoginVerification,CanSeeManagedUsers,IsPasswordResetRequired\r\n,,AMCLI,,,123 Fake St.,8675309,Programmer,,,,,TRUE,,,,,,\r\n,am@donttrustthewizard.com,AM WIZARD,,,,,,,,,,,,,,,,"
  },
  {
    "path": "docs/Bulk actions/users/transfer-content.csv",
    "content": "USERID,NEWUSERID\r\n123456789,2468013579\r\n987654321,2468013579\r\n135792468,2468013579\r\n246813579,2468013579"
  },
  {
    "path": "docs/Bulk actions/users/update-users.csv",
    "content": "id,name\n1234567890,4-293927-33\n2468013579,4-294293-11\n1357924680,4-295219-21\n1111111111,4-296188-11\n2222222222,4-297829-94\n3333333333,4-298111-12\n4444444444,4-299827-49\n5555555555,4-230991-02\n6666666666,4-231182-04\n7777777777,\"Jack Johnson\"\n8888888888,\"John Doe\"\n9999999999,\"Jane Doe\""
  },
  {
    "path": "docs/Bulk actions/users/users.md",
    "content": "`box users`\n===========\n\nManage users\n\n* [`box users:create NAME [LOGIN]`](#box-userscreate-name-login)\n* [`box users:transfer-content USERID NEWUSERID`](#box-userstransfer-content-userid-newuserid)\n* [`box users:update ID`](#box-usersupdate-id)\n\n\n## `box users:create NAME [LOGIN]`\n\nCreate a new Box User\n\n```\nUSAGE\n  $ box users:create NAME [LOGIN]\n\nARGUMENTS\n  NAME   The user's name\n  LOGIN  The user's email address, not required when creating app users\n\n\nEXAMPLE\n  box users:create --bulk-file-path path/to/csv/create-users.csv\n```\n\n_See documentation [users.md](https://github.com/box/boxcli/blob/main/docs/users.md#box-userscreate-name-login)_\n_See example: [create-users.csv](create-users.csv)_\n\n\n## `box users:transfer-content USERID NEWUSERID`\n\nMove a user's root content to another user\n\n```\nUSAGE\n  $ box users:transfer-content USERID NEWUSERID\n\nARGUMENTS\n  USERID     User whose content should be moved\n  NEWUSERID  User to whom the content should be moved\n\nALIASES\n  $ box users:move-root-content\n\nEXAMPLE\n  box users:transfer-content --bulk-file-path path/to/csv/transfer-content.csv\n```\n\n_See documentation [users.md](https://github.com/box/boxcli/blob/main/docs/users.md#box-userstransfer-content-userid-newuserid)_\n_See example: [transfer-content.csv](transfer-content.csv)_\n\n\n## `box users:update ID`\n\nUpdate a Box User\n\n```\nUSAGE\n  $ box users:update ID\n\nARGUMENTS\n  ID  User ID to update\n\nEXAMPLE\n  box users:update --bulk-file-path path/to/csv/update-users.csv\n```\n\n- _See documentation [users.md](https://github.com/box/boxcli/blob/main/docs/users.md#box-usersupdate-id)_\n- _See example: [update-users.csv](update-users.csv)_\n"
  },
  {
    "path": "docs/Bulk actions/webhooks/webhooks-delete.csv",
    "content": "Id,Triggers,TargetId,TargetType\r\n5898184,,30341904974,folder\r\n5898351,,29726196007,folder"
  },
  {
    "path": "docs/Bulk actions/webhooks/webhooks.md",
    "content": "`box webhooks`\n===========\n\nManage webhooks\n\n* [`box webhooks:delete ID`](#box-webhooksdelete-id)\n\n\n## `box webhooks:delete ID`\n\nDelete a webhook\n\n```\nUSAGE\n  $ box webhooks:delete ID\n\nARGUMENTS\n  ID  ID of the webhook to delete\n\nOPTIONS\n  -h, --help                             Show CLI help\n  -q, --quiet                            Suppress any non-error output to stderr\n  -s, --save                             Save report to default reports folder on disk\n  -t, --token=token                      Provide a token to perform this call\n  -v, --verbose                          Show verbose output, which can be helpful for debugging\n  -y, --yes                              Automatically respond yes to all confirmation prompts\n  --as-user=as-user                      Provide an ID for a user\n  --bulk-file-path=bulk-file-path        File path to bulk .csv or .json objects\n  --csv                                  Output formatted CSV\n  --fields=fields                        Comma separated list of fields to show\n  --json                                 Output formatted JSON\n  --no-color                             Turn off colors for logging\n  --save-to-file-path=save-to-file-path  Override default file path to save report\n\nEXAMPLE\n  box webhooks:delete --bulk-file-path path/to/csv/file.csv --save-to-file-path path/to/destination/folder\n```\n\n- _See documentation [webhooks.md](https://github.com/box/boxcli/blob/main/docs/webhooks.md#box-webhooksdelete-id)_\n- _See example: [webhooks-delete.csv](webhooks-delete.csv)_\n"
  },
  {
    "path": "docs/ai.md",
    "content": "`box ai`\n========\n\nSends a request to supported LLMs using Box AI. This is intended for direct use, not by AI agents.\n\n* [`box ai:ask`](#box-aiask)\n* [`box ai:extract`](#box-aiextract)\n* [`box ai:extract-structured`](#box-aiextract-structured)\n* [`box ai:text-gen`](#box-aitext-gen)\n\n## `box ai:ask`\n\nSends a request to supported LLMs using Box AI. This is intended for direct use, not by AI agents.\n\n```\nUSAGE\n  $ box ai:ask --prompt <value> --items <value>... [-t <value>] [--as-user <value>] [--no-color] [--json |\n    --csv] [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n    [--ai-agent <value>] [--raw-json | ]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --ai-agent=<value>           AI agent configuration as JSON. Example:\n                                   {\"type\":\"ai_agent_ask\",\"basic_text\":{\"model\":\"azure__openai__gpt_4o_mini\"}}\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --items=<value>...           (required) Items for the AI request. Format: id=FILE_ID,type=file (or\n                                   content=TEXT,type=file). Supported keys: id, type, content.\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --prompt=<value>             (required) The prompt for the AI request\n      --raw-json                   Output the raw API JSON response instead of the tsClient-normalized object fields.\n                                   Added as a non-breaking compatibility flag for users who need JSON field names to\n                                   match the API schema exactly. Implies --json.\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Sends a request to supported LLMs using Box AI. This is intended for direct use, not by AI agents.\n\nEXAMPLES\n  $ box ai:ask --items=id=12345,type=file --prompt \"What is the status of this document?\"\n```\n\n_See code: [src/commands/ai/ask.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/ai/ask.js)_\n\n## `box ai:extract`\n\nSends an AI request to supported Large Language Models (LLMs) and extracts metadata in form of key-value pairs. This is intended for direct use, not by AI agents.\n\n```\nUSAGE\n  $ box ai:extract --prompt <value> --items <value>... [-t <value>] [--as-user <value>] [--no-color] [--json |\n    --csv] [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n    [--raw-json | ] [--ai-agent <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --ai-agent=<value>           AI agent configuration as JSON. Example: {\"type\":\"ai_agent_extract\",\"basic_text\":{\"mo\n                                   del\":\"azure__openai__gpt_4o_mini\",\"prompt_template\":\"Answer the question based on\n                                   {content}\"}}\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --items=<value>...           (required) Items for extraction. Format: id=FILE_ID,type=file (or\n                                   content=TEXT,type=file). Supported keys: id, type, content.\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --prompt=<value>             (required) The prompt provided to a Large Language Model (LLM) in the request.\n      --raw-json                   Output the raw API JSON response instead of the tsClient-normalized object fields.\n                                   Added as a non-breaking compatibility flag for users who need JSON field names to\n                                   match the API schema exactly. Implies --json.\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Sends an AI request to supported Large Language Models (LLMs) and extracts metadata in form of key-value pairs. This\n  is intended for direct use, not by AI agents.\n\nEXAMPLES\n  $ box ai:extract --items=id=12345,type=file --prompt \"firstName, lastName, location, yearOfBirth, company\"\n\n  $ box ai:extract --prompt \"firstName, lastName, location, yearOfBirth, company\" --items \"id=12345,type=file\" --ai-agent '{\"type\":\"ai_agent_extract\",\"basic_text\":{\"model\":\"azure__openai__gpt_4o_mini\"}}'\n```\n\n_See code: [src/commands/ai/extract.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/ai/extract.js)_\n\n## `box ai:extract-structured`\n\nSends an AI request to supported Large Language Models (LLMs) and returns extracted metadata as a set of key-value pairs. For this request, you either need a metadata template or a list of fields you want to extract. Input is either a metadata template or a list of fields to ensure the structure. This is intended for direct use, not by AI agents.\n\n```\nUSAGE\n  $ box ai:extract-structured --items <value>... [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>...] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n    [--metadata-template <value>] [--ai-agent <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --ai-agent=<value>           AI agent configuration as JSON. Example: {\"type\":\"ai_agent_extract_structured\",\"basic\n                                   _text\":{\"model\":\"azure__openai__gpt_4o_mini\",\"prompt_template\":\"Answer the question\n                                   based on {content}\"}}\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>...          Fields to extract from the provided items. Use options=VALUE1;VALUE2 for multiSelect\n                                   fields.\n      --items=<value>...           (required) Items for structured extraction. Format: id=FILE_ID,type=file (or\n                                   content=TEXT,type=file). Supported keys: id, type, content.\n      --json                       Output formatted JSON\n      --metadata-template=<value>  The metadata template containing the fields to extract.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Sends an AI request to supported Large Language Models (LLMs) and returns extracted metadata as a set of key-value\n  pairs. For this request, you either need a metadata template or a list of fields you want to extract. Input is either\n  a metadata template or a list of fields to ensure the structure. This is intended for direct use, not by AI agents.\n\nEXAMPLES\n  $ box ai:extract-structured --items=\"id=12345,type=file\" --fields \"key=hobby,type=multiSelect,description=Person hobby,prompt=What is your hobby?,displayName=Hobby,options=Guitar;Books\"\n\n  $ box ai:extract-structured --items=\"id=12345,type=file\" --metadata-template=\"type=metadata_template,scope=enterprise,template_key=test\" --ai-agent '{\"type\":\"ai_agent_extract_structured\",\"basic_text\":{\"model\":\"azure__openai__gpt_4o_mini\",\"prompt_template\":\"Answer using the provided content\"}}'\n```\n\n_See code: [src/commands/ai/extract-structured.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/ai/extract-structured.js)_\n\n## `box ai:text-gen`\n\nSends an AI request to supported LLMs and returns an answer specifically focused on the creation of new text. This is intended for direct use, not by AI agents.\n\n```\nUSAGE\n  $ box ai:text-gen --items <value>... --prompt <value> [-t <value>] [--as-user <value>] [--no-color] [--json |\n    --csv] [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n    [--dialogue-history <value>...]\n\nFLAGS\n  -h, --help                         Show CLI help\n  -q, --quiet                        Suppress any non-error output to stderr\n  -s, --save                         Save report to default reports folder on disk\n  -t, --token=<value>                Provide a token to perform this call\n  -v, --verbose                      Show verbose output, which can be helpful for debugging\n  -y, --yes                          Automatically respond yes to all confirmation prompts\n      --as-user=<value>              Provide an ID for a user\n      --bulk-file-path=<value>       File path to bulk .csv or .json objects\n      --csv                          Output formatted CSV\n      --dialogue-history=<value>...  The history of prompts and answers previously passed to the LLM.\n      --fields=<value>               Comma separated list of fields to show\n      --items=<value>...             (required) Items for text generation. Format: id=FILE_ID,type=file (or\n                                     content=TEXT,type=file). Supported keys: id, type, content. Exactly one item is\n                                     supported.\n      --json                         Output formatted JSON\n      --no-color                     Turn off colors for logging\n      --prompt=<value>               (required) The prompt for the AI request\n      --save-to-file-path=<value>    Override default file path to save report\n\nDESCRIPTION\n  Sends an AI request to supported LLMs and returns an answer specifically focused on the creation of new text. This is\n  intended for direct use, not by AI agents.\n\nEXAMPLES\n  $ box ai:text-gen --dialogue-history=prompt=\"What is the status of this document?\",answer=\"It is in review\",created-at=\"2024-07-09T11:29:46.835Z\" --items=id=12345,type=file --prompt=\"What is the status of this document?\"\n```\n\n_See code: [src/commands/ai/text-gen.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/ai/text-gen.js)_\n"
  },
  {
    "path": "docs/authentication.md",
    "content": "Authentication\n==============\n\nSee the [OAuth 2 overview](https://developer.box.com/en/guides/authentication/) for a detailed\noverview of how the Box API handles authentication.\n\n- [Ways to Authenticate](#ways-to-authenticate)\n  - [Developer Token](#developer-token)\n  - [Server Auth with JWT](#server-auth-with-jwt)\n  - [Server Auth with CCG](#server-auth-with-ccg)\n  - [OAuth 2.0 Login (`box login`)](#oauth-20-login-box-login)\n    - [Option 1: Official Box CLI App](#option-1-official-box-cli-app)\n    - [Option 2: Your Own Platform App](#option-2-your-own-platform-app)\n    - [Supported Ports](#supported-ports)\n    - [Additional Flags](#additional-flags)\n    - [Reauthorize OAuth2](#reauthorize-oauth2)\n\n\nWays to Authenticate\n--------------------\n\nUse this quick comparison to choose the right method:\n\n| Method | Best for | User interaction | Main setup command |\n|--------|----------|------------------|--------------------|\n| Developer Token | Quick local testing | Manual token copy/paste | Use `--token` on any command |\n| OAuth 2.0 (`box login`) | Interactive user workflows | Yes (browser auth) | `box login -d` (quick start) |\n| JWT | Server-to-server automation | No | `box configure:environments:add /path/to/config.json` |\n| CCG | Server-to-server automation (no keypair) | No | `box configure:environments:add /path/to/config.json --ccg-auth` |\n\n### Developer Token\n\nA developer token is a token that you can generate directly from the [Box Developer Console][dev-console]. It provides a quick way to test API calls without setting up a full authentication flow.\n\n[dev-console]: https://app.box.com/developers/console\n\n**Key characteristics:**\n\n- Cannot be refreshed.\n- Scoped to your own account only.\n- Intended for **development and testing** — not suitable for production use.\n\n**Usage** — pass the token to any CLI command with the `--token` flag:\n\n```bash\nbox users:get --token <DEVELOPER_TOKEN>\n```\n\n> **Tip:** You can generate a new developer token at any time from the **Configuration** tab of your application in the [Developer Console][dev-console].\n\n### Server Auth with JWT\n\nJSON Web Token (JWT) authentication allows your application to authenticate as a [Service Account](https://developer.box.com/platform/user-types#service-account) without requiring user interaction. This is ideal for server-to-server integrations, automated workflows, and backend services.\n\n**Key characteristics:**\n\n- The application authenticates on behalf of a **Service Account**, which is separate from any individual user's account.\n- Files stored in the Service Account are not accessible from other accounts by default, and vice versa.\n- Requires a public/private key pair, which can be generated automatically in the [Developer Console][dev-console].\n\n**Setup:**\n\n1. In the [Developer Console][dev-console], create or open an application that uses **JWT** authentication.\n2. Generate a public/private key pair (or upload your own). This produces a JSON configuration file.\n3. Download the configuration file and add it as an environment:\n\n```bash\nbox configure:environments:add /path/to/config.json --name 'YOUR_ENVIRONMENT_NAME'\n```\n\n4. If you have multiple environments, set the active one:\n\n```bash\nbox configure:environments:set-current\n```\n\nAfter setup, all CLI commands will authenticate using the JWT credentials from the selected environment.\n\n### Server Auth with CCG\n\nClient Credentials Grant (CCG) authentication allows your application to authenticate as a [Service Account](https://developer.box.com/platform/user-types#service-account) using a **Client ID**, **Client Secret**, and **Enterprise ID**. Like JWT, this method is designed for server-to-server communication and does not require user interaction.\n\n**Key characteristics:**\n\n- The application authenticates on behalf of a **Service Account**, which is separate from any individual user's account.\n- Files stored in the Service Account are not accessible from other accounts by default, and vice versa.\n- No key pair generation is needed — authentication relies on the Client ID and Client Secret only.\n\n**Setup:**\n\n1. In the [Developer Console][dev-console], create or open an application that uses **Client Credentials Grant** authentication.\n2. Create a JSON configuration file with the following structure:\n\n```json\n{\n  \"boxAppSettings\": {\n    \"clientID\": \"your_client_id\",\n    \"clientSecret\": \"your_client_secret\"\n  },\n  \"enterpriseID\": \"your_enterprise_id\"\n}\n```\n\n> **Tip:** You can find the `clientID` and `clientSecret` values in the **Configuration** tab, and the `enterpriseID` in the **General Settings** tab of your application in the [Developer Console][dev-console].\n\n3. Add the environment with the `--ccg-auth` flag:\n\n```bash\nbox configure:environments:add /path/to/config.json --ccg-auth --name 'YOUR_ENVIRONMENT_NAME'\n```\n\n4. If you have multiple environments, set the active one:\n\n```bash\nbox configure:environments:set-current\n```\n\n**Authenticating as a specific user:**\n\nBy default, CCG authenticates as the Service Account. To make API calls as an App User or Managed User instead, pass the `--ccg-user` flag with the user's ID:\n\n```bash\nbox configure:environments:add /path/to/config.json --ccg-auth --ccg-user \"USER_ID\"\n```\n\n### OAuth 2.0 Login (`box login`)\n\nThe `box login` command authenticates you with Box using OAuth 2.0. It starts a local callback server, opens your browser for authorization, and stores the resulting tokens in a named environment.\n\nWhen you run `box login`, the CLI presents three options: the **Official Box CLI App**, a **Platform App** you create yourself, or **quit** (`q`) to exit. You can either choose interactively or skip the selection entirely using the `--default-box-app` (`-d`) flag. You can also paste a Client ID directly at the prompt — any input between 16 and 99 characters is treated as a Client ID.\n\n#### Option 1: Official Box CLI App\n\nThis is the fastest way to get started with Box CLI. No app creation in the Box Developer Console is required — just run the command and authorize.\n\n**Interactive selection** — run `box login` and choose option `1` to use the built-in app, `2` for a Platform App, or `q` to quit:\n\n```bash\nbox login\n# Choose [1] for Official Box CLI App, [2] for Platform App, or [q] to quit.\n```\n\n**Skip the prompt** — use the `--default-box-app` (or `-d`) flag to go directly to authorization:\n\n```bash\nbox login --default-box-app\n```\n\n```bash\nbox login -d\n```\n\n> **Note:** The Official Box CLI App uses scopes limited to content actions, which allows you to effectively manage your files and folders. If you need broader scopes (e.g., managing users, groups, or enterprise settings), use your own Platform App instead.\n\n#### Option 2: Your Own Platform App\n\nIf you need customized scopes or a dedicated application, you can log in with your own OAuth app. When prompted, enter the **Client ID** and **Client Secret** from your application's configuration.\n\nBefore running the command, set up the app in the [Box Developer Console](https://cloud.app.box.com/developers/console):\n\n1. Select an application with **OAuth 2.0 user authentication** (or create a new Platform App).\n2. In the **Configuration** tab, set the **Redirect URI** to `http://localhost:3000/callback` (adjust the port if you use a different `--port` value).\n3. Click **Save Changes**.\n\nThen log in:\n\n```bash\nbox login\n# Choose [2] when prompted, then enter your Client ID and Client Secret.\n# Alternatively, paste your Client ID directly at the prompt (any input between 16 and 99 characters is recognized as a Client ID).\n```\n\nFor a step-by-step walkthrough, see the [Quickstart Guide](https://developer.box.com/guides/tooling/cli/quick-start/).\n\n#### Supported Ports\n\nThe `box login` command starts a local callback server to receive the OAuth redirect. You can control the port with the `--port` (`-p`) flag. The default port is **3000**.\n\nWhen using the **Official Box CLI App**, only the following ports are supported:\n\n| Port | Command |\n|------|---------|\n| 3000 | `box login -d` (default) |\n| 3001 | `box login -d --port 3001` |\n| 4000 | `box login -d --port 4000` |\n| 5000 | `box login -d --port 5000` |\n| 8080 | `box login -d --port 8080` |\n\nWhen using your own Platform App, any port can be used — just make sure the **Redirect URI** in the Developer Console matches `http://localhost:<port>/callback`.\n\n#### Additional Flags\n\n| Flag | Short | Description                                                                          |\n|------|-------|--------------------------------------------------------------------------------------|\n| `--default-box-app` | `-d` | Use the Official Box CLI App and proceed directly to authorization.                  |\n| `--platform-app` | | Skip the prompt and go directly to Platform App setup (Client ID and Client Secret). |\n| `--port <number>` | `-p` | Set the port for the local callback server. Default: `3000`.                         |\n| `--name <string>` | `-n` | Set a name for the environment. Default: `oauth`.                                    |\n| `--reauthorize` | `-r` | Reauthorize an existing environment (requires `--name`).                             |\n| `--code` | `-c` | Manually visit the authorize URL and input the auth code.                            |\n| `--incognito-browser` | `-i` | Open the authorize URL in a private/incognito browser window.                        |\n\n#### Reauthorize OAuth2\n\nAfter each successful OAuth 2.0 authorization, a pair of tokens is generated: an **Access Token** and a **Refresh Token**.\n\n- The [Access Token](https://developer.box.com/guides/authentication/tokens/access-tokens/) represents the authenticated user and is valid for **60 minutes**.\n- The [Refresh Token](https://developer.box.com/guides/authentication/tokens/refresh/) is used to obtain a new Access Token. It is valid for **1 use within 60 days**.\n\nIf both tokens expire, you will see the following error:\n\n```\nYour refresh token has expired.\nPlease run this command \"box login --name <ENVIRONMENT_NAME> --reauthorize\" to reauthorize selected environment and then run your command again.\n```\n\nTo reauthorize, run:\n\n```bash\nbox login --name \"ENVIRONMENT_NAME\" --reauthorize\n```\n\nThe `--reauthorize` flag retrieves the existing `clientID` and `clientSecret` from the stored environment, so you do not need to enter them again. After a successful login, the environment is updated and set as the default.\n\nYou can also combine `--reauthorize` with `--default-box-app` to switch an existing environment to the Official Box CLI App:\n\n```bash\nbox login --name \"ENVIRONMENT_NAME\" --reauthorize --default-box-app\n```\n"
  },
  {
    "path": "docs/autocomplete.md",
    "content": "`box autocomplete`\n==================\n\nDisplay autocomplete installation instructions\n\n* [`box autocomplete [SHELL]`](#box-autocomplete-shell)\n\n## `box autocomplete [SHELL]`\n\nDisplay autocomplete installation instructions.\n\n```\nUSAGE\n  $ box autocomplete [SHELL] [-r]\n\nARGUMENTS\n  [SHELL]  (zsh|bash|powershell) Shell type\n\nFLAGS\n  -r, --refresh-cache  Refresh cache (ignores displaying instructions)\n\nDESCRIPTION\n  Display autocomplete installation instructions.\n\nEXAMPLES\n  $ box autocomplete\n\n  $ box autocomplete bash\n\n  $ box autocomplete zsh\n\n  $ box autocomplete powershell\n\n  $ box autocomplete --refresh-cache\n```\n\n_See code: [@oclif/plugin-autocomplete](https://github.com/oclif/plugin-autocomplete/blob/v3.2.39/src/commands/autocomplete/index.js)_\n"
  },
  {
    "path": "docs/collaboration-allowlist.md",
    "content": "`box collaboration-allowlist`\n=============================\n\nList collaboration allowlist entries\n\n* [`box collaboration-allowlist`](#box-collaboration-allowlist)\n* [`box collaboration-allowlist:add DOMAIN`](#box-collaboration-allowlistadd-domain)\n* [`box collaboration-allowlist:delete ID`](#box-collaboration-allowlistdelete-id)\n* [`box collaboration-allowlist:exemptions`](#box-collaboration-allowlistexemptions)\n* [`box collaboration-allowlist:exemptions:create USERID`](#box-collaboration-allowlistexemptionscreate-userid)\n* [`box collaboration-allowlist:exemptions:delete ID`](#box-collaboration-allowlistexemptionsdelete-id)\n* [`box collaboration-allowlist:exemptions:get ID`](#box-collaboration-allowlistexemptionsget-id)\n* [`box collaboration-allowlist:get ID`](#box-collaboration-allowlistget-id)\n\n## `box collaboration-allowlist`\n\nList collaboration allowlist entries\n\n```\nUSAGE\n  $ box collaboration-allowlist [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List collaboration allowlist entries\n\nEXAMPLES\n  $ box collaboration-allowlist\n```\n\n_See code: [src/commands/collaboration-allowlist/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collaboration-allowlist/index.js)_\n\n## `box collaboration-allowlist:add DOMAIN`\n\nAdd a collaboration allowlist entry\n\n```\nUSAGE\n  $ box collaboration-allowlist:add DOMAIN --direction inbound|outbound|both [-t <value>] [--as-user <value>] [--no-color]\n    [--json | --csv] [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y]\n    [-q]\n\nARGUMENTS\n  DOMAIN  Domain to add to allowlist (e.g. box.com)\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --direction=<option>         (required) Direction to allowlist collaboration in\n                                   <options: inbound|outbound|both>\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Add a collaboration allowlist entry\n\nEXAMPLES\n  $ box collaboration-allowlist:add example.com --direction outbound\n```\n\n_See code: [src/commands/collaboration-allowlist/add.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collaboration-allowlist/add.js)_\n\n## `box collaboration-allowlist:delete ID`\n\nDelete a collaboration allowlist entry\n\n```\nUSAGE\n  $ box collaboration-allowlist:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the collaboration allowlist entry record to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a collaboration allowlist entry\n\nEXAMPLES\n  $ box collaboration-allowlist:delete 12345\n```\n\n_See code: [src/commands/collaboration-allowlist/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collaboration-allowlist/delete.js)_\n\n## `box collaboration-allowlist:exemptions`\n\nList collaboration allowlist exemptions\n\n```\nUSAGE\n  $ box collaboration-allowlist:exemptions [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List collaboration allowlist exemptions\n\nEXAMPLES\n  $ box collaboration-allowlist:exemptions\n```\n\n_See code: [src/commands/collaboration-allowlist/exemptions/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collaboration-allowlist/exemptions/index.js)_\n\n## `box collaboration-allowlist:exemptions:create USERID`\n\nExempt a user from the collaboration allowlist\n\n```\nUSAGE\n  $ box collaboration-allowlist:exemptions:create USERID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  USERID  ID of the user to exempt from the collaboration allowlist\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Exempt a user from the collaboration allowlist\n\nEXAMPLES\n  $ box collaboration-allowlist:exemptions:create 11111\n```\n\n_See code: [src/commands/collaboration-allowlist/exemptions/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collaboration-allowlist/exemptions/create.js)_\n\n## `box collaboration-allowlist:exemptions:delete ID`\n\nDelete a collaboration allowlist exemption\n\n```\nUSAGE\n  $ box collaboration-allowlist:exemptions:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the allowlist exemption record to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a collaboration allowlist exemption\n\nEXAMPLES\n  $ box collaboration-allowlist:exemptions:delete 12345\n```\n\n_See code: [src/commands/collaboration-allowlist/exemptions/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collaboration-allowlist/exemptions/delete.js)_\n\n## `box collaboration-allowlist:exemptions:get ID`\n\nGet a collaboration allowlist exemption\n\n```\nUSAGE\n  $ box collaboration-allowlist:exemptions:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the allowlist exemption record to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get a collaboration allowlist exemption\n\nEXAMPLES\n  $ box collaboration-allowlist:exemptions:get 12345\n```\n\n_See code: [src/commands/collaboration-allowlist/exemptions/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collaboration-allowlist/exemptions/get.js)_\n\n## `box collaboration-allowlist:get ID`\n\nGet a collaboration allowlist entry\n\n```\nUSAGE\n  $ box collaboration-allowlist:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the collaboration allowlist entry record to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get a collaboration allowlist entry\n\nEXAMPLES\n  $ box collaboration-allowlist:get 12345\n```\n\n_See code: [src/commands/collaboration-allowlist/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collaboration-allowlist/get.js)_\n"
  },
  {
    "path": "docs/collaboration-whitelist.md",
    "content": "Please see [Collaboration Allowlist](collaboration-allowlist.md)."
  },
  {
    "path": "docs/collaborations.md",
    "content": "`box collaborations`\n====================\n\nManage collaborations\n\n* [`box collaborations:add ITEMID ITEMTYPE`](#box-collaborationsadd-itemid-itemtype)\n* [`box collaborations:create ITEMID ITEMTYPE`](#box-collaborationscreate-itemid-itemtype)\n* [`box collaborations:delete ID`](#box-collaborationsdelete-id)\n* [`box collaborations:get ID`](#box-collaborationsget-id)\n* [`box collaborations:get-pending`](#box-collaborationsget-pending)\n* [`box collaborations:list-for-group ID`](#box-collaborationslist-for-group-id)\n* [`box collaborations:pending`](#box-collaborationspending)\n* [`box collaborations:update ID`](#box-collaborationsupdate-id)\n\n## `box collaborations:add ITEMID ITEMTYPE`\n\nCreate a collaboration for a Box item\n\n```\nUSAGE\n  $ box collaborations:add ITEMID ITEMTYPE [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-r\n    editor|viewer|previewer|uploader|previewer_uploader|viewer_uploader|co-owner |  |  |  |  |  |  | ] [--user-id\n    <value> | --group-id <value> | --login <value>] [--can-view-path] [--id-only] [--notify]\n\nARGUMENTS\n  ITEMID    The ID of the Box item to add the collaboration to\n  ITEMTYPE  (file|folder) The type of the Box item to add the collaboration to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -r, --role=<option>              An option to manually enter the role\n                                   <options:\n                                   editor|viewer|previewer|uploader|previewer_uploader|viewer_uploader|co-owner>\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-view-path         Whether view path collaboration feature is enabled or not\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --group-id=<value>           Id for group to collaborate\n      --id-only                    Return only an ID to output from this command\n      --json                       Output formatted JSON\n      --login=<value>              Login for user to collaborate\n      --no-color                   Turn off colors for logging\n      --[no-]notify                All users will receive email notification of the collaboration\n      --save-to-file-path=<value>  Override default file path to save report\n      --user-id=<value>            Id for user to collaborate\n\nDESCRIPTION\n  Create a collaboration for a Box item\n\nALIASES\n  $ box collaborations:add\n\nEXAMPLES\n  $ box collaborations:create 22222 folder --role editor --user-id 33333\n```\n\n## `box collaborations:create ITEMID ITEMTYPE`\n\nCreate a collaboration for a Box item\n\n```\nUSAGE\n  $ box collaborations:create ITEMID ITEMTYPE [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-r\n    editor|viewer|previewer|uploader|previewer_uploader|viewer_uploader|co-owner |  |  |  |  |  |  | ] [--user-id\n    <value> | --group-id <value> | --login <value>] [--can-view-path] [--id-only] [--notify]\n\nARGUMENTS\n  ITEMID    The ID of the Box item to add the collaboration to\n  ITEMTYPE  (file|folder) The type of the Box item to add the collaboration to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -r, --role=<option>              An option to manually enter the role\n                                   <options:\n                                   editor|viewer|previewer|uploader|previewer_uploader|viewer_uploader|co-owner>\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-view-path         Whether view path collaboration feature is enabled or not\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --group-id=<value>           Id for group to collaborate\n      --id-only                    Return only an ID to output from this command\n      --json                       Output formatted JSON\n      --login=<value>              Login for user to collaborate\n      --no-color                   Turn off colors for logging\n      --[no-]notify                All users will receive email notification of the collaboration\n      --save-to-file-path=<value>  Override default file path to save report\n      --user-id=<value>            Id for user to collaborate\n\nDESCRIPTION\n  Create a collaboration for a Box item\n\nALIASES\n  $ box collaborations:add\n\nEXAMPLES\n  $ box collaborations:create 22222 folder --role editor --user-id 33333\n```\n\n_See code: [src/commands/collaborations/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collaborations/create.js)_\n\n## `box collaborations:delete ID`\n\nRemove a collaboration\n\n```\nUSAGE\n  $ box collaborations:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  The ID of the collaboration to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Remove a collaboration\n\nALIASES\n  $ box files:collaborations:delete\n  $ box folders:collaborations:delete\n\nEXAMPLES\n  $ box collaborations:delete 12345\n```\n\n_See code: [src/commands/collaborations/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collaborations/delete.js)_\n\n## `box collaborations:get ID`\n\nGet an individual collaboration\n\n```\nUSAGE\n  $ box collaborations:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the collaboration to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get an individual collaboration\n\nEXAMPLES\n  $ box collaborations:get 12345\n```\n\n_See code: [src/commands/collaborations/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collaborations/get.js)_\n\n## `box collaborations:get-pending`\n\nList all pending collaborations for a user\n\n```\nUSAGE\n  $ box collaborations:get-pending [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all pending collaborations for a user\n\nALIASES\n  $ box collaborations:get-pending\n\nEXAMPLES\n  $ box collaborations:pending\n```\n\n## `box collaborations:list-for-group ID`\n\nList collaborations for a group\n\n```\nUSAGE\n  $ box collaborations:list-for-group ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the group to get collaborations for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List collaborations for a group\n\nALIASES\n  $ box groups:list-collaborations\n  $ box collaborations:list-for-group\n\nEXAMPLES\n  $ box groups:collaborations 12345\n```\n\n## `box collaborations:pending`\n\nList all pending collaborations for a user\n\n```\nUSAGE\n  $ box collaborations:pending [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all pending collaborations for a user\n\nALIASES\n  $ box collaborations:get-pending\n\nEXAMPLES\n  $ box collaborations:pending\n```\n\n_See code: [src/commands/collaborations/pending.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collaborations/pending.js)_\n\n## `box collaborations:update ID`\n\nUpdate a collaboration\n\n```\nUSAGE\n  $ box collaborations:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-r\n    editor|viewer|previewer|uploader|previewer_uploader|viewer_uploader|co-owner|owner |  |  |  |  |  |  |  | ]\n    [--status accepted|pending|rejected] [--can-view-path] [--expires-at <value>]\n\nARGUMENTS\n  ID  The ID of the collaboration to update\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -r, --role=<option>              An option to manually enter the role\n                                   <options:\n                                   editor|viewer|previewer|uploader|previewer_uploader|viewer_uploader|co-owner|owner>\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-view-path         Whether view path collaboration feature is enabled or not\n      --csv                        Output formatted CSV\n      --expires-at=<value>         When the collaboration should expire\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --status=<option>            Update the collaboration status\n                                   <options: accepted|pending|rejected>\n\nDESCRIPTION\n  Update a collaboration\n\nALIASES\n  $ box files:collaborations:update\n  $ box folders:collaborations:update\n\nEXAMPLES\n  $ box collaborations:update 12345 --role viewer\n```\n\n_See code: [src/commands/collaborations/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collaborations/update.js)_\n"
  },
  {
    "path": "docs/collections.md",
    "content": "`box collections`\n=================\n\nList your collections\n\n* [`box collections`](#box-collections)\n* [`box collections:add ITEMTYPE ITEMID COLLECTIONID`](#box-collectionsadd-itemtype-itemid-collectionid)\n* [`box collections:items ID`](#box-collectionsitems-id)\n* [`box collections:list`](#box-collectionslist)\n* [`box collections:remove ITEMTYPE ITEMID COLLECTIONID`](#box-collectionsremove-itemtype-itemid-collectionid)\n\n## `box collections`\n\nList your collections\n\n```\nUSAGE\n  $ box collections [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List your collections\n\nALIASES\n  $ box collections:list\n\nEXAMPLES\n  $ box collections\n```\n\n_See code: [src/commands/collections/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collections/index.js)_\n\n## `box collections:add ITEMTYPE ITEMID COLLECTIONID`\n\nAdd an item to a collection\n\n```\nUSAGE\n  $ box collections:add ITEMTYPE ITEMID COLLECTIONID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv]\n    [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ITEMTYPE      (folder|file|web_link) Type of item\n  ITEMID        ID of the of item\n  COLLECTIONID  ID of collection\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Add an item to a collection\n\nEXAMPLES\n  $ box collections:add file 11111 12345\n```\n\n_See code: [src/commands/collections/add.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collections/add.js)_\n\n## `box collections:items ID`\n\nGet items in a collection\n\n```\nUSAGE\n  $ box collections:items ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  ID  ID of the collection to retrieve the items of\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get items in a collection\n\nEXAMPLES\n  $ box collections:items 12345\n```\n\n_See code: [src/commands/collections/items.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collections/items.js)_\n\n## `box collections:list`\n\nList your collections\n\n```\nUSAGE\n  $ box collections:list [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List your collections\n\nALIASES\n  $ box collections:list\n\nEXAMPLES\n  $ box collections\n```\n\n## `box collections:remove ITEMTYPE ITEMID COLLECTIONID`\n\nRemove an item from a collection\n\n```\nUSAGE\n  $ box collections:remove ITEMTYPE ITEMID COLLECTIONID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv]\n    [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ITEMTYPE      (folder|file) Type of item\n  ITEMID        ID of item\n  COLLECTIONID  ID of collection\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Remove an item from a collection\n\nEXAMPLES\n  $ box collections:remove file 11111 12345\n```\n\n_See code: [src/commands/collections/remove.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/collections/remove.js)_\n"
  },
  {
    "path": "docs/comments.md",
    "content": "`box comments`\n==============\n\nManage comments on files\n\n* [`box comments:create FILEID`](#box-commentscreate-fileid)\n* [`box comments:delete ID`](#box-commentsdelete-id)\n* [`box comments:get ID`](#box-commentsget-id)\n* [`box comments:list ID`](#box-commentslist-id)\n* [`box comments:reply ID`](#box-commentsreply-id)\n* [`box comments:update ID`](#box-commentsupdate-id)\n\n## `box comments:create FILEID`\n\nCreate a comment on a file\n\n```\nUSAGE\n  $ box comments:create FILEID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--message <value> |\n    --tagged-message <value>]\n\nARGUMENTS\n  FILEID  ID of file on which to comment\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --message=<value>            Message of comment\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --tagged-message=<value>     The text of the comment, including @[userid:Username] somewhere in the message to\n                                   mention the user\n\nDESCRIPTION\n  Create a comment on a file\n\nEXAMPLES\n  $ box comments:create 11111 --message \"Thanks for the update!\"\n```\n\n_See code: [src/commands/comments/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/comments/create.js)_\n\n## `box comments:delete ID`\n\nDelete a comment\n\n```\nUSAGE\n  $ box comments:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the comment to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a comment\n\nEXAMPLES\n  $ box comments:delete 12345\n```\n\n_See code: [src/commands/comments/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/comments/delete.js)_\n\n## `box comments:get ID`\n\nGet information about a comment\n\n```\nUSAGE\n  $ box comments:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the comment to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a comment\n\nEXAMPLES\n  $ box comments:get 12345\n```\n\n_See code: [src/commands/comments/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/comments/get.js)_\n\n## `box comments:list ID`\n\nList all comments on a file\n\n```\nUSAGE\n  $ box comments:list ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the file to get comments for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all comments on a file\n\nALIASES\n  $ box comments:list\n\nEXAMPLES\n  $ box files:comments 11111\n```\n\n## `box comments:reply ID`\n\nReply to a comment\n\n```\nUSAGE\n  $ box comments:reply ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--message <value> | --tagged-message\n    <value>]\n\nARGUMENTS\n  ID  ID of the comment to reply to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --message=<value>            Message of comment\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --tagged-message=<value>     The text of the comment, including @[userid:Username] somewhere in the message to\n                                   mention the user\n\nDESCRIPTION\n  Reply to a comment\n\nEXAMPLES\n  $ box comments:reply 12345 --message \"No problem!\"\n```\n\n_See code: [src/commands/comments/reply.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/comments/reply.js)_\n\n## `box comments:update ID`\n\nUpdate a comment\n\n```\nUSAGE\n  $ box comments:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--message <value> | --tagged-message\n    <value>]\n\nARGUMENTS\n  ID  ID of the comment to update\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --message=<value>            The text of the comment\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --tagged-message=<value>     The tagged text of the comment\n\nDESCRIPTION\n  Update a comment\n\nEXAMPLES\n  $ box comments:update 12345 --message \"Thank you for the update!\"\n```\n\n_See code: [src/commands/comments/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/comments/update.js)_\n"
  },
  {
    "path": "docs/configuration.md",
    "content": "# Configuration\nTo configure Box CLI the method [configure].\nYou can have many environments that define how you authenticate to box but there is only one configuration shared across them.\nTo see current configuration run:\n```commandline\n box configure:settings\n```\n\nYou can also configure CLI settings by changing the `~/.box/settings.json` file.\n\nTopics covered in this guide include:\n - [Using `settings` command](#using-settings-command)\n   - [Setting up proxy](#setting-up-proxy)\n - [Using configuration file](#using-configuration-file)\n   - [Configure how client retries calls and handles timeouts](#configure-how-client-retries-calls-and-handles-timeouts)\n   - [Configure base URL](#configure-base-url)\n\n\n# Using `settings` command\n## Setting up proxy\n\nTo configure proxy you will need:\n* Proxy URL, which should contain the protocol, url, and port (i.e. http://sample.proxyurl.com:80)\n* Username and Password if required\n\nUse [configure] command to set up proxy:\n```commandline\nbox configure:settings --enable-proxy\\\n --proxy-url=proxy-url\\\n --proxy-username=proxy-username\\\n --proxy-password=proxy-password\n```\n\nThe output should contain proxy settings:\n```commandline\nProxy:\n    URL: proxy-url\n    Username: proxy-username\n    Password: proxy-password\n```\n\nNow every call will be using configured proxy. To disable proxy settings run:\n```commandline\nbox configure:settings --no-enable-proxy\n```\n\nProxy settings are not removed from your configuration, this command disables proxy setting by CLI.\nYou can enable proxy once again (will be using previous settings) with:\n```commandline\nbox configure:settings --enable-proxy\n```\n\n# Using configuration file\nYou can find configuration file here `~/.box/settings.json`. This file will be created by running [configure] command \nand changing any setting. \n\n```json\n{\n  \"boxReportsFolderPath\": \"path_where_to_store_reports\",\n  \"boxReportsFileFormat\": \"txt\",\n  \"boxDownloadsFolderPath\": \"path_where_to_store_downloads\",\n  \"outputJson\": false,\n  \"enableProxy\": false,\n  \"proxy\": {\n\t\"url\": null,\n\t\"username\": null,\n\t\"password\": null\n  }\n}\n```\n\n- `boxReportsFolderPath`: the folder path to store reports\n- `boxReportsFileFormat`: the file format for generated reports, possible values: `csv`, `json`, `txt`\n- `boxDownloadsFolderPath`: folder path for the downloads folder\n- `outputJson`: sets JSON output for all commands, possible values: `true`, `false`\n- `enableProxy`: Enable (`true`) or disable (`false`) proxy\n- `proxy.url`: proxy url, which should contain the protocol, url, and port (i.e. http://sample.proxyurl.com:80)\n- `proxy.username`: username for proxy\n- `proxy.password`: password for proxy\n\n## Configure how client retries calls and handles timeouts\n\nYou can configure how many retries, how long to wait between retries or upload timeout. The default values are already\ndefined for the CLI but if you want to change default behaviour add those options to `settings.json`\n\n```json\n{\n  \"numMaxRetries\": 3,\n  \"retryIntervalMS\": 3000,\n  \"uploadRequestTimeoutMS\": 90000\n}\n```\n\n- `numMaxRetries`: the maximum number of retries when API request fails. Default value is `5`.\n\n- `retryIntervalMS`: is used to calculate the wait time between retries. It is a number of miliseconds. SDK\nuses `Exponential backoff` algorithm to calculate the wait time. Default value is `2000` ms.\n\n- `uploadRequestTimeoutMS`: the timeout after which an upload request is aborted Default value is `60000` ms.\n\n### Configure base URL\n\nThe Base Url is the URL that is used by the SDK to access Box. The default base URLs are already defined for the CLI but\nif you want to change default behaviour add those options to `settings.json`\n\n```json\n{\n  \"apiRootURL\": \"https://my.company.url.com\",\n  \"uploadAPIRootURL\": \"https://my.company.url.com/upload\",\n  \"authorizeRootURL\": \"https://my.company.url.com/authorize\"\n}\n```\n\nThe `apiRootURL` sets to what URL all API calls will be directed.\n\nThe `uploadAPIRootURL` is used to configure the base URL used while uploading files.\n\nThe `authorizeRootURL` is used to configure the base URL used to obtain OAuth2 authorization tokens.\n\n[configure]: configure.md\n"
  },
  {
    "path": "docs/configure.md",
    "content": "`box configure`\n===============\n\nConfigure the Box CLI\n\n* [`box configure:environments:add PATH`](#box-configureenvironmentsadd-path)\n* [`box configure:environments:delete [NAME]`](#box-configureenvironmentsdelete-name)\n* [`box configure:environments:get`](#box-configureenvironmentsget)\n* [`box configure:environments:list`](#box-configureenvironmentslist)\n* [`box configure:environments:select [ID]`](#box-configureenvironmentsselect-id)\n* [`box configure:environments:set-current [ID]`](#box-configureenvironmentsset-current-id)\n* [`box configure:environments:switch-user [USERID]`](#box-configureenvironmentsswitch-user-userid)\n* [`box configure:environments:update [NAME]`](#box-configureenvironmentsupdate-name)\n* [`box configure:settings`](#box-configuresettings)\n\n## `box configure:environments:add PATH`\n\nAdd a new Box environment from a Box app config file (JWT or CCG).\n\n```\nUSAGE\n  $ box configure:environments:add PATH [--no-color] [-h] [-v] [-q] [--private-key-path <value>] [--set-as-current] [-n <value>]\n    [--ccg-user <value> --ccg-auth]\n\nARGUMENTS\n  PATH\n      Path to the Box app configuration JSON file.\n      JWT: download this file from your application in Developer Console:\n      https://cloud.app.box.com/developers/console\n      CCG: create this JSON file yourself using values from your application\n      in Developer Console (Client ID and Client Secret from Configuration tab,\n      Enterprise ID from General Settings tab).\n\nFLAGS\n  -h, --help\n      Show CLI help\n\n  -n, --name=<value>\n      [default: default] Set a name for the environment\n\n  -q, --quiet\n      Suppress any non-error output to stderr\n\n  -v, --verbose\n      Show verbose output, which can be helpful for debugging\n\n  --ccg-auth\n      Add a CCG environment that will use a service account.\n      Open your application in Box Developer Console and create this config JSON yourself.\n      Required fields: boxAppSettings.clientID, boxAppSettings.clientSecret, enterpriseID.\n\n  --ccg-user=<value>\n      Provide an ID for a user for CCG. Use it to obtain user token. In order to enable generating user token you have to\n      go to your application configuration that can be found here https://app.box.com/developers/console.\n      In`Configuration` tab, in section `Advanced Features` select `Generate user access tokens`.\n      Do not forget to re-authorize application if it was already authorized.\n\n  --no-color\n      Turn off colors for logging\n\n  --private-key-path=<value>\n      Provide a path to application private key\n\n  --set-as-current\n      Set this new environment as your current environment\n\nDESCRIPTION\n  Add a new Box environment from a Box app config file (JWT or CCG).\n  Open your application in Box Developer Console to get/create config data:\n  https://cloud.app.box.com/developers/console\n\n  For OAuth (an alternative to server-side auth), add environment with: box login.\n  Quick start: box login -d (logs the user in via the Box Official CLI App).\n\nEXAMPLES\n  $ box configure:environments:add ~/Downloads/my_app_config.json\n\n  $ box configure:environments:add ./config.json --name production --set-as-current\n\n  $ box configure:environments:add ./config.json --ccg-auth --name ci-bot\n```\n\n_See code: [src/commands/configure/environments/add.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/configure/environments/add.js)_\n\n## `box configure:environments:delete [NAME]`\n\nDelete a Box environment\n\n```\nUSAGE\n  $ box configure:environments:delete [NAME] [--no-color] [-h] [-v] [-q]\n\nARGUMENTS\n  [NAME]  Name of the environment\n\nFLAGS\n  -h, --help      Show CLI help\n  -q, --quiet     Suppress any non-error output to stderr\n  -v, --verbose   Show verbose output, which can be helpful for debugging\n      --no-color  Turn off colors for logging\n\nDESCRIPTION\n  Delete a Box environment\n```\n\n_See code: [src/commands/configure/environments/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/configure/environments/delete.js)_\n\n## `box configure:environments:get`\n\nGet a Box environment or list all configured Box environments.\n\n```\nUSAGE\n  $ box configure:environments:get [--no-color] [-h] [-v] [-q] [-c | -n <value>]\n\nFLAGS\n  -c, --current       Get the current default Box environment\n  -h, --help          Show CLI help\n  -n, --name=<value>  Get a Box environment with this name\n  -q, --quiet         Suppress any non-error output to stderr\n  -v, --verbose       Show verbose output, which can be helpful for debugging\n      --no-color      Turn off colors for logging\n\nDESCRIPTION\n  Get a Box environment or list all configured Box environments.\n  clientSecret values are masked in CLI output. To view full secrets, access secure storage directly (for example, macOS\n  Keychain, Windows Credential Manager, or a supported Linux equivalent).\n\nALIASES\n  $ box configure:environments:list\n```\n\n_See code: [src/commands/configure/environments/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/configure/environments/get.js)_\n\n## `box configure:environments:list`\n\nGet a Box environment or list all configured Box environments.\n\n```\nUSAGE\n  $ box configure:environments:list [--no-color] [-h] [-v] [-q] [-c | -n <value>]\n\nFLAGS\n  -c, --current       Get the current default Box environment\n  -h, --help          Show CLI help\n  -n, --name=<value>  Get a Box environment with this name\n  -q, --quiet         Suppress any non-error output to stderr\n  -v, --verbose       Show verbose output, which can be helpful for debugging\n      --no-color      Turn off colors for logging\n\nDESCRIPTION\n  Get a Box environment or list all configured Box environments.\n  clientSecret values are masked in CLI output. To view full secrets, access secure storage directly (for example, macOS\n  Keychain, Windows Credential Manager, or a supported Linux equivalent).\n\nALIASES\n  $ box configure:environments:list\n```\n\n## `box configure:environments:select [ID]`\n\nSet your current Box environment to use\n\n```\nUSAGE\n  $ box configure:environments:select [ID] [--no-color] [-h] [-v] [-q]\n\nARGUMENTS\n  [ID]  Name of the environment\n\nFLAGS\n  -h, --help      Show CLI help\n  -q, --quiet     Suppress any non-error output to stderr\n  -v, --verbose   Show verbose output, which can be helpful for debugging\n      --no-color  Turn off colors for logging\n\nDESCRIPTION\n  Set your current Box environment to use\n\nALIASES\n  $ box configure:environments:select\n```\n\n## `box configure:environments:set-current [ID]`\n\nSet your current Box environment to use\n\n```\nUSAGE\n  $ box configure:environments:set-current [ID] [--no-color] [-h] [-v] [-q]\n\nARGUMENTS\n  [ID]  Name of the environment\n\nFLAGS\n  -h, --help      Show CLI help\n  -q, --quiet     Suppress any non-error output to stderr\n  -v, --verbose   Show verbose output, which can be helpful for debugging\n      --no-color  Turn off colors for logging\n\nDESCRIPTION\n  Set your current Box environment to use\n\nALIASES\n  $ box configure:environments:select\n```\n\n_See code: [src/commands/configure/environments/set-current.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/configure/environments/set-current.js)_\n\n## `box configure:environments:switch-user [USERID]`\n\nSwitch the default Box user to run commands as\n\n```\nUSAGE\n  $ box configure:environments:switch-user [USERID] [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--default]\n\nARGUMENTS\n  [USERID]  The user ID to switch to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --default                    Switch to the default user, i.e. the Service Account\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Switch the default Box user to run commands as\n```\n\n_See code: [src/commands/configure/environments/switch-user.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/configure/environments/switch-user.js)_\n\n## `box configure:environments:update [NAME]`\n\nUpdate a Box environment\n\n```\nUSAGE\n  $ box configure:environments:update [NAME] [--no-color] [-h] [-v] [-q] [--config-file-path <value>] [--name <value>]\n    [--private-key-path <value>] [--user-id <value>] [--cache-tokens]\n\nARGUMENTS\n  [NAME]  The name of the environment\n\nFLAGS\n  -h, --help                      Show CLI help\n  -q, --quiet                     Suppress any non-error output to stderr\n  -v, --verbose                   Show verbose output, which can be helpful for debugging\n      --[no-]cache-tokens         Enable token caching, which significantly improves performance. Run with\n                                  --no-cache-tokens and then --cache-tokens if your application config updates are not\n                                  reflected in your requests.\n      --config-file-path=<value>  Provide a file path to configuration file\n      --name=<value>              New name of the environment\n      --no-color                  Turn off colors for logging\n      --private-key-path=<value>  Provide a file path to application private key\n      --user-id=<value>           Store a default user ID to use with the session commands. A default user ID can be\n                                  stored for each Box environment\n\nDESCRIPTION\n  Update a Box environment\n```\n\n_See code: [src/commands/configure/environments/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/configure/environments/update.js)_\n\n## `box configure:settings`\n\nView and update CLI configuration settings\n\n```\nUSAGE\n  $ box configure:settings [--no-color] [-h] [-v] [-q] [--json] [--enable-proxy] [--proxy-url <value>] [--proxy-username\n    <value> --proxy-password <value>] [--downloads-folder-path <value>] [--file-format csv|json|txt] [--output-json]\n    [--reports-folder-path <value>] [--enable-analytics-client] [--analytics-client-name <value>]\n\nFLAGS\n  -h, --help                           Show CLI help\n  -q, --quiet                          Suppress any non-error output to stderr\n  -v, --verbose                        Show verbose output, which can be helpful for debugging\n      --analytics-client-name=<value>  Set custom analytics client header value\n      --downloads-folder-path=<value>  Set folder path for the downloads folder\n      --[no-]enable-analytics-client   Enable or disable custom analytics client\n      --[no-]enable-proxy              Enable or disable proxy\n      --file-format=<option>           Set the file format for generated reports\n                                       <options: csv|json|txt>\n      --json                           Output CLI configuration settings in JSON format\n      --no-color                       Turn off colors for logging\n      --[no-]output-json               Default to JSON output for all commands\n      --proxy-password=<value>         Set password for proxy\n      --proxy-url=<value>              Set proxy url, which should contain the protocol, url, and port (i.e.\n                                       http://sample.proxyurl.com:80)\n      --proxy-username=<value>         Set username for proxy\n      --reports-folder-path=<value>    Set folder path for the reports folder\n\nDESCRIPTION\n  View and update CLI configuration settings\n```\n\n_See code: [src/commands/configure/settings.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/configure/settings.js)_\n"
  },
  {
    "path": "docs/device-pins.md",
    "content": "`box device-pins`\n=================\n\nList all the device pins for your enterprise\n\n* [`box device-pins`](#box-device-pins)\n* [`box device-pins:delete ID`](#box-device-pinsdelete-id)\n* [`box device-pins:get ID`](#box-device-pinsget-id)\n\n## `box device-pins`\n\nList all the device pins for your enterprise\n\n```\nUSAGE\n  $ box device-pins [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--direction\n    ASC|DESC]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --direction=<option>         Set sorting (by id) direction. Default is ASC\n                                   <options: ASC|DESC>\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all the device pins for your enterprise\n\nEXAMPLES\n  $ box device-pins\n```\n\n_See code: [src/commands/device-pins/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/device-pins/index.js)_\n\n## `box device-pins:delete ID`\n\nDelete individual device pin\n\n```\nUSAGE\n  $ box device-pins:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the device pin to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete individual device pin\n\nEXAMPLES\n  $ box device-pins:delete 12345\n```\n\n_See code: [src/commands/device-pins/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/device-pins/delete.js)_\n\n## `box device-pins:get ID`\n\nGet information about an individual device pin\n\n```\nUSAGE\n  $ box device-pins:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the device pin to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about an individual device pin\n\nEXAMPLES\n  $ box device-pins:get 12345\n```\n\n_See code: [src/commands/device-pins/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/device-pins/get.js)_\n"
  },
  {
    "path": "docs/events.md",
    "content": "`box events`\n============\n\nGet events\n\n* [`box events`](#box-events)\n* [`box events:get`](#box-eventsget)\n* [`box events:poll`](#box-eventspoll)\n\n## `box events`\n\nGet events\n\n```\nUSAGE\n  $ box events [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--event-types <value>]\n    [--stream-position <value> | [--created-before <value> ] | [--created-after <value> -e]] [--limit <value>]\n    [--stream-type admin_logs|admin_logs_streaming ]\n\nFLAGS\n  -e, --enterprise\n      Get all enterprise events form a given criteria.\n      CLI will use the `next_stream_position` automatically to fetch all records.\n\n  -h, --help\n      Show CLI help\n\n  -q, --quiet\n      Suppress any non-error output to stderr\n\n  -s, --save\n      Save report to default reports folder on disk\n\n  -t, --token=<value>\n      Provide a token to perform this call\n\n  -v, --verbose\n      Show verbose output, which can be helpful for debugging\n\n  -y, --yes\n      Automatically respond yes to all confirmation prompts\n\n  --as-user=<value>\n      Provide an ID for a user\n\n  --bulk-file-path=<value>\n      File path to bulk .csv or .json objects\n\n  --created-after=<value>\n      Return enterprise events that occurred after a time. Use a timestamp or shorthand syntax 0t, like 5w for 5 weeks. If\n      not used, defaults to 5 days before the end date\n\n  --created-before=<value>\n      Return enterprise events that occurred before a time. Use a timestamp or shorthand syntax 0t, like 5w for 5 weeks.\n      If not used, defaults to now\n\n  --csv\n      Output formatted CSV\n\n  --event-types=<value>\n      Return enterprise events filtered by event types. Format using a comma delimited list:\n      NEW_USER,DELETE_USER,EDIT_USER\n\n  --fields=<value>\n      Comma separated list of fields to show\n\n  --json\n      Output formatted JSON\n\n  --limit=<value>\n      The maximum number of items to return.\n      When using it with `enterprise` events, it determines the number of items to return per API call. The CLI will\n      automatically use the `next_stream_position` to fetch all records.\n\n  --no-color\n      Turn off colors for logging\n\n  --save-to-file-path=<value>\n      Override default file path to save report\n\n  --stream-position=<value>\n      The location in the event stream from which you want to start receiving events\n\n  --stream-type=<option>\n      Stream type admin_logs or admin_logs_streaming.\n      Unless specified `admin_logs` stream type is used.\n\n      The emphasis for `admin_logs` stream is on completeness over latency, which means that Box will deliver admin events\n      in chronological order and without duplicates, but with higher latency. You can specify start and end time/dates.\n\n      The emphasis for `admin_logs_streaming` feed is on low latency rather than chronological accuracy, which means that\n      Box may return events more than once and out of chronological order. Events are returned via the API around 12\n      seconds after they are processed by Box (the 12 seconds buffer ensures that new events are not written after your\n      cursor position). Only two weeks of events are available via this feed, and you cannot set start and end time/dates.\n      <options: admin_logs|admin_logs_streaming>\n\nDESCRIPTION\n  Get events\n\nALIASES\n  $ box events:get\n\nEXAMPLES\n  $ box events\n\n  $ box events --enterprise --created-after 2019-01-01\n```\n\n_See code: [src/commands/events/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/events/index.js)_\n\n## `box events:get`\n\nGet events\n\n```\nUSAGE\n  $ box events:get [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--event-types <value>]\n    [--stream-position <value> | [--created-before <value> ] | [--created-after <value> -e]] [--limit <value>]\n    [--stream-type admin_logs|admin_logs_streaming ]\n\nFLAGS\n  -e, --enterprise\n      Get all enterprise events form a given criteria.\n      CLI will use the `next_stream_position` automatically to fetch all records.\n\n  -h, --help\n      Show CLI help\n\n  -q, --quiet\n      Suppress any non-error output to stderr\n\n  -s, --save\n      Save report to default reports folder on disk\n\n  -t, --token=<value>\n      Provide a token to perform this call\n\n  -v, --verbose\n      Show verbose output, which can be helpful for debugging\n\n  -y, --yes\n      Automatically respond yes to all confirmation prompts\n\n  --as-user=<value>\n      Provide an ID for a user\n\n  --bulk-file-path=<value>\n      File path to bulk .csv or .json objects\n\n  --created-after=<value>\n      Return enterprise events that occurred after a time. Use a timestamp or shorthand syntax 0t, like 5w for 5 weeks. If\n      not used, defaults to 5 days before the end date\n\n  --created-before=<value>\n      Return enterprise events that occurred before a time. Use a timestamp or shorthand syntax 0t, like 5w for 5 weeks.\n      If not used, defaults to now\n\n  --csv\n      Output formatted CSV\n\n  --event-types=<value>\n      Return enterprise events filtered by event types. Format using a comma delimited list:\n      NEW_USER,DELETE_USER,EDIT_USER\n\n  --fields=<value>\n      Comma separated list of fields to show\n\n  --json\n      Output formatted JSON\n\n  --limit=<value>\n      The maximum number of items to return.\n      When using it with `enterprise` events, it determines the number of items to return per API call. The CLI will\n      automatically use the `next_stream_position` to fetch all records.\n\n  --no-color\n      Turn off colors for logging\n\n  --save-to-file-path=<value>\n      Override default file path to save report\n\n  --stream-position=<value>\n      The location in the event stream from which you want to start receiving events\n\n  --stream-type=<option>\n      Stream type admin_logs or admin_logs_streaming.\n      Unless specified `admin_logs` stream type is used.\n\n      The emphasis for `admin_logs` stream is on completeness over latency, which means that Box will deliver admin events\n      in chronological order and without duplicates, but with higher latency. You can specify start and end time/dates.\n\n      The emphasis for `admin_logs_streaming` feed is on low latency rather than chronological accuracy, which means that\n      Box may return events more than once and out of chronological order. Events are returned via the API around 12\n      seconds after they are processed by Box (the 12 seconds buffer ensures that new events are not written after your\n      cursor position). Only two weeks of events are available via this feed, and you cannot set start and end time/dates.\n      <options: admin_logs|admin_logs_streaming>\n\nDESCRIPTION\n  Get events\n\nALIASES\n  $ box events:get\n\nEXAMPLES\n  $ box events\n\n  $ box events --enterprise --created-after 2019-01-01\n```\n\n## `box events:poll`\n\nPoll the event stream\n\n```\nUSAGE\n  $ box events:poll [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-e] [--event-types <value>]\n    [--start-date <value>] [--end-date <value>] [--polling-interval <value>]\n\nFLAGS\n  -e, --enterprise                 Get enterprise events\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --end-date=<value>           Return enterprise events that occured before this time. Use a timestamp or shorthand\n                                   syntax 00t, like 05w for 5 weeks.\n      --event-types=<value>        Return enterprise events filtered by event types. Format using a comma delimited\n                                   list: NEW_USER,DELETE_USER,EDIT_USER\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --polling-interval=<value>   Number of seconds to wait before polling for new events. Default is 60 seconds.\n      --save-to-file-path=<value>  Override default file path to save report\n      --start-date=<value>         Return enterprise events that occured after this time. Use a timestamp or shorthand\n                                   syntax 00t, like 05w for 5 weeks. If not used, defaults to now\n\nDESCRIPTION\n  Poll the event stream\n```\n\n_See code: [src/commands/events/poll.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/events/poll.js)_\n"
  },
  {
    "path": "docs/file-requests.md",
    "content": "`box file-requests`\n===================\n\nCopies existing file request to new folder\n\n* [`box file-requests:copy ID FOLDERID`](#box-file-requestscopy-id-folderid)\n* [`box file-requests:delete ID`](#box-file-requestsdelete-id)\n* [`box file-requests:get ID`](#box-file-requestsget-id)\n* [`box file-requests:update ID`](#box-file-requestsupdate-id)\n\n## `box file-requests:copy ID FOLDERID`\n\nCopies existing file request to new folder\n\n```\nUSAGE\n  $ box file-requests:copy ID FOLDERID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--description\n    <value>] [--expires-at <value>] [--description-required] [--email-required] [--status active|inactive] [--title\n    <value>]\n\nARGUMENTS\n  ID        ID of the file request to copy\n  FOLDERID  ID of folder to which file request will be copied\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --description=<value>        New description of file request\n      --[no-]description-required  is file request submitter required to provide a description of the files they are\n                                   submitting\n      --[no-]email-required        New date when file request expires\n      --expires-at=<value>         New date when file request expires\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --status=<option>            New status of file request\n                                   <options: active|inactive>\n      --title=<value>              New title of file request\n\nDESCRIPTION\n  Copies existing file request to new folder\n\nEXAMPLES\n  $ box file-requests:copy 22222 44444\n```\n\n_See code: [src/commands/file-requests/copy.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/file-requests/copy.js)_\n\n## `box file-requests:delete ID`\n\nDelete individual file request\n\n```\nUSAGE\n  $ box file-requests:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the file request to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete individual file request\n\nEXAMPLES\n  $ box file-requests:delete 12345\n```\n\n_See code: [src/commands/file-requests/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/file-requests/delete.js)_\n\n## `box file-requests:get ID`\n\nGet information about an file request\n\n```\nUSAGE\n  $ box file-requests:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the file request to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about an file request\n\nEXAMPLES\n  $ box file-requests:get 12345\n```\n\n_See code: [src/commands/file-requests/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/file-requests/get.js)_\n\n## `box file-requests:update ID`\n\nUpdate a file request\n\n```\nUSAGE\n  $ box file-requests:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--description <value>] [--expires-at\n    <value>] [--description-required] [--email-required] [--status active|inactive] [--title <value>] [--etag <value>]\n\nARGUMENTS\n  ID  ID of the file request to update\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --description=<value>        New description of file request\n      --[no-]description-required  is file request submitter required to provide a description of the files they are\n                                   submitting\n      --[no-]email-required        New date when file request expires\n      --etag=<value>               Pass in the item's last observed etag value into this header and the endpoint will\n                                   fail with a 412 Precondition Failed if it has changed since.\n      --expires-at=<value>         New date when file request expires\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --status=<option>            New status of file request\n                                   <options: active|inactive>\n      --title=<value>              New title of file request\n\nDESCRIPTION\n  Update a file request\n\nEXAMPLES\n  $ box file-requests:update 12345 --description \"New file request description!\"\n```\n\n_See code: [src/commands/file-requests/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/file-requests/update.js)_\n"
  },
  {
    "path": "docs/files.md",
    "content": "`box files`\n===========\n\nManage files\n\n* [`box files:collaborations ID`](#box-filescollaborations-id)\n* [`box files:collaborations:add ID`](#box-filescollaborationsadd-id)\n* [`box files:collaborations:delete ID`](#box-filescollaborationsdelete-id)\n* [`box files:collaborations:list ID`](#box-filescollaborationslist-id)\n* [`box files:collaborations:update ID`](#box-filescollaborationsupdate-id)\n* [`box files:comments ID`](#box-filescomments-id)\n* [`box files:copy ID PARENTID`](#box-filescopy-id-parentid)\n* [`box files:delete ID`](#box-filesdelete-id)\n* [`box files:download ID`](#box-filesdownload-id)\n* [`box files:get ID`](#box-filesget-id)\n* [`box files:lock ID`](#box-fileslock-id)\n* [`box files:metadata ID`](#box-filesmetadata-id)\n* [`box files:metadata:add ID`](#box-filesmetadataadd-id)\n* [`box files:metadata:create ID`](#box-filesmetadatacreate-id)\n* [`box files:metadata:delete ID`](#box-filesmetadatadelete-id)\n* [`box files:metadata:get ID`](#box-filesmetadataget-id)\n* [`box files:metadata:get-all ID`](#box-filesmetadataget-all-id)\n* [`box files:metadata:remove ID`](#box-filesmetadataremove-id)\n* [`box files:metadata:set ID`](#box-filesmetadataset-id)\n* [`box files:metadata:update ID`](#box-filesmetadataupdate-id)\n* [`box files:move ID PARENTID`](#box-filesmove-id-parentid)\n* [`box files:rename ID NAME`](#box-filesrename-id-name)\n* [`box files:share ID`](#box-filesshare-id)\n* [`box files:shared-links:create ID`](#box-filesshared-linkscreate-id)\n* [`box files:shared-links:delete ID`](#box-filesshared-linksdelete-id)\n* [`box files:shared-links:update ID`](#box-filesshared-linksupdate-id)\n* [`box files:tasks ID`](#box-filestasks-id)\n* [`box files:tasks:list ID`](#box-filestaskslist-id)\n* [`box files:unlock ID`](#box-filesunlock-id)\n* [`box files:unshare ID`](#box-filesunshare-id)\n* [`box files:update ID`](#box-filesupdate-id)\n* [`box files:update-lock ID`](#box-filesupdate-lock-id)\n* [`box files:upload PATH`](#box-filesupload-path)\n* [`box files:versions FILEID`](#box-filesversions-fileid)\n* [`box files:versions:delete FILEID FILEVERSIONID`](#box-filesversionsdelete-fileid-fileversionid)\n* [`box files:versions:download FILEID FILEVERSIONID`](#box-filesversionsdownload-fileid-fileversionid)\n* [`box files:versions:list FILEID`](#box-filesversionslist-fileid)\n* [`box files:versions:promote FILEID FILEVERSIONID`](#box-filesversionspromote-fileid-fileversionid)\n* [`box files:versions:upload FILEID PATH`](#box-filesversionsupload-fileid-path)\n* [`box files:zip NAME`](#box-fileszip-name)\n\n## `box files:collaborations ID`\n\nList all collaborations on a file\n\n```\nUSAGE\n  $ box files:collaborations ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  ID  ID of the file to get collaborations for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all collaborations on a file\n\nALIASES\n  $ box files:collaborations:list\n\nEXAMPLES\n  $ box files:collaborations 11111\n```\n\n_See code: [src/commands/files/collaborations/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/collaborations/index.js)_\n\n## `box files:collaborations:add ID`\n\nCreate a collaboration for a file\n\n```\nUSAGE\n  $ box files:collaborations:add ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-r\n    editor|viewer|previewer|uploader|previewer_uploader|viewer_uploader|co-owner |  |  |  |  |  |  | ] [--user-id\n    <value> | --group-id <value> | --login <value>] [--can-view-path] [--id-only] [--notify]\n\nARGUMENTS\n  ID  ID of the file to add a collaboration to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -r, --role=<option>              An option to manually enter the role\n                                   <options:\n                                   editor|viewer|previewer|uploader|previewer_uploader|viewer_uploader|co-owner>\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-view-path         Whether view path collaboration feature is enabled or not\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --group-id=<value>           Id for group to collaborate\n      --id-only                    Return only an ID to output from this command\n      --json                       Output formatted JSON\n      --login=<value>              Login for user to collaborate\n      --no-color                   Turn off colors for logging\n      --[no-]notify                All users will receive email notification of the collaboration\n      --save-to-file-path=<value>  Override default file path to save report\n      --user-id=<value>            Id for user to collaborate\n\nDESCRIPTION\n  Create a collaboration for a file\n\nEXAMPLES\n  $ box files:collaborations:add 11111 --role editor --user-id 22222\n```\n\n_See code: [src/commands/files/collaborations/add.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/collaborations/add.js)_\n\n## `box files:collaborations:delete ID`\n\nRemove a collaboration\n\n```\nUSAGE\n  $ box files:collaborations:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  The ID of the collaboration to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Remove a collaboration\n\nALIASES\n  $ box files:collaborations:delete\n  $ box folders:collaborations:delete\n\nEXAMPLES\n  $ box collaborations:delete 12345\n```\n\n## `box files:collaborations:list ID`\n\nList all collaborations on a file\n\n```\nUSAGE\n  $ box files:collaborations:list ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  ID  ID of the file to get collaborations for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all collaborations on a file\n\nALIASES\n  $ box files:collaborations:list\n\nEXAMPLES\n  $ box files:collaborations 11111\n```\n\n## `box files:collaborations:update ID`\n\nUpdate a collaboration\n\n```\nUSAGE\n  $ box files:collaborations:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-r\n    editor|viewer|previewer|uploader|previewer_uploader|viewer_uploader|co-owner|owner |  |  |  |  |  |  |  | ]\n    [--status accepted|pending|rejected] [--can-view-path] [--expires-at <value>]\n\nARGUMENTS\n  ID  The ID of the collaboration to update\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -r, --role=<option>              An option to manually enter the role\n                                   <options:\n                                   editor|viewer|previewer|uploader|previewer_uploader|viewer_uploader|co-owner|owner>\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-view-path         Whether view path collaboration feature is enabled or not\n      --csv                        Output formatted CSV\n      --expires-at=<value>         When the collaboration should expire\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --status=<option>            Update the collaboration status\n                                   <options: accepted|pending|rejected>\n\nDESCRIPTION\n  Update a collaboration\n\nALIASES\n  $ box files:collaborations:update\n  $ box folders:collaborations:update\n\nEXAMPLES\n  $ box collaborations:update 12345 --role viewer\n```\n\n## `box files:comments ID`\n\nList all comments on a file\n\n```\nUSAGE\n  $ box files:comments ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the file to get comments for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all comments on a file\n\nALIASES\n  $ box comments:list\n\nEXAMPLES\n  $ box files:comments 11111\n```\n\n_See code: [src/commands/files/comments.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/comments.js)_\n\n## `box files:copy ID PARENTID`\n\nCopy a file to a different folder\n\n```\nUSAGE\n  $ box files:copy ID PARENTID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--name <value>]\n    [--version <value>] [--id-only]\n\nARGUMENTS\n  ID        ID of the file to copy\n  PARENTID  ID of the new parent folder to copy the file into\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --id-only                    Output only the ID of the file copy\n      --json                       Output formatted JSON\n      --name=<value>               New name for the file\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --version=<value>            File version ID if you want to copy a specific file version\n\nDESCRIPTION\n  Copy a file to a different folder\n\nEXAMPLES\n  $ box files:copy 11111 22222\n```\n\n_See code: [src/commands/files/copy.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/copy.js)_\n\n## `box files:delete ID`\n\nDelete a file\n\n```\nUSAGE\n  $ box files:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-f] [--etag <value>]\n\nARGUMENTS\n  ID  ID of the file to delete\n\nFLAGS\n  -f, --force                      Permanently delete the item, bypassing the trash\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --etag=<value>               Only delete if etag value matches\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a file\n\nEXAMPLES\n  $ box files:delete 11111\n```\n\n_See code: [src/commands/files/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/delete.js)_\n\n## `box files:download ID`\n\nDownload a file\n\n```\nUSAGE\n  $ box files:download ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--version <value>] [--destination\n    <value>] [--create-path] [--overwrite] [--save-as <value>]\n\nARGUMENTS\n  ID  ID of the file to download\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]create-path           Recursively creates a path to a directory if it does not exist\n      --csv                        Output formatted CSV\n      --destination=<value>        The destination folder to write the file to\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --[no-]overwrite             Overwrite a file if it already exists (prevents overwrite prompt)\n      --save-as=<value>            The filename used when saving the file\n      --save-to-file-path=<value>  Override default file path to save report\n      --version=<value>            File version ID of the specific file version to download\n\nDESCRIPTION\n  Download a file\n\nEXAMPLES\n  $ box files:download 11111 --destination /path/to/destinationFolder\n```\n\n_See code: [src/commands/files/download.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/download.js)_\n\n## `box files:get ID`\n\nGet information about a file\n\n```\nUSAGE\n  $ box files:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the file to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a file\n\nEXAMPLES\n  $ box files:get 11111\n```\n\n_See code: [src/commands/files/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/get.js)_\n\n## `box files:lock ID`\n\nLock a file\n\n```\nUSAGE\n  $ box files:lock ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--expires <value>] [--prevent-download]\n\nARGUMENTS\n  ID  ID of file to lock\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --expires=<value>            Make the lock expire from a timespan set from now. Use s for seconds, m for minutes,\n                                   h for hours, d for days, w for weeks, M for months. For example, 30 seconds is 30s\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --[no-]prevent-download      Prevent download of locked file\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Lock a file\n\nALIASES\n  $ box files:update-lock\n\nEXAMPLES\n  $ box files:lock 11111\n```\n\n_See code: [src/commands/files/lock.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/lock.js)_\n\n## `box files:metadata ID`\n\nGet all metadata on a file\n\n```\nUSAGE\n  $ box files:metadata ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  Id of the file\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get all metadata on a file\n\nALIASES\n  $ box files:metadata:get-all\n\nEXAMPLES\n  $ box files:metadata 11111\n```\n\n_See code: [src/commands/files/metadata/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/metadata/index.js)_\n\n## `box files:metadata:add ID`\n\nAdd metadata to a file\n\n```\nUSAGE\n  $ box files:metadata:add ID --data <value>... --template-key <value> [-t <value>] [--as-user <value>] [--no-color]\n    [--json | --csv] [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y]\n    [-q] [--scope <value>]\n\nARGUMENTS\n  ID  ID of the file to add metadata to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --data=<value>...            (required) Metadata key and value, in the form \"key=value\".  Note: For float type,\n                                   use \"#\" at the beginning of digits: key2=#1234.50\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to use\n      --template-key=<value>       (required) The key of the metadata template to use\n\nDESCRIPTION\n  Add metadata to a file\n\nALIASES\n  $ box files:metadata:create\n\nEXAMPLES\n  $ box files:metadata:add 11111 --template-key employeeRecord --data \"name=John Doe\" --data department=Sales\n\n  $ box files:metadata:add 22222 --template-key myTemplate --data \"multiselectkey1=[option1A,option1B]\" --data \"multiselectkey2=[option2A]\"\n```\n\n_See code: [src/commands/files/metadata/add.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/metadata/add.js)_\n\n## `box files:metadata:create ID`\n\nAdd metadata to a file\n\n```\nUSAGE\n  $ box files:metadata:create ID --data <value>... --template-key <value> [-t <value>] [--as-user <value>] [--no-color]\n    [--json | --csv] [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y]\n    [-q] [--scope <value>]\n\nARGUMENTS\n  ID  ID of the file to add metadata to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --data=<value>...            (required) Metadata key and value, in the form \"key=value\".  Note: For float type,\n                                   use \"#\" at the beginning of digits: key2=#1234.50\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to use\n      --template-key=<value>       (required) The key of the metadata template to use\n\nDESCRIPTION\n  Add metadata to a file\n\nALIASES\n  $ box files:metadata:create\n\nEXAMPLES\n  $ box files:metadata:add 11111 --template-key employeeRecord --data \"name=John Doe\" --data department=Sales\n\n  $ box files:metadata:add 22222 --template-key myTemplate --data \"multiselectkey1=[option1A,option1B]\" --data \"multiselectkey2=[option2A]\"\n```\n\n## `box files:metadata:delete ID`\n\nDelete metadata from a file\n\n```\nUSAGE\n  $ box files:metadata:delete ID --template-key <value> [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s\n    | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--scope <value>]\n\nARGUMENTS\n  ID  ID of the file to remove metadata from\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to remove\n      --template-key=<value>       (required) The key of the metadata template to remove\n\nDESCRIPTION\n  Delete metadata from a file\n\nALIASES\n  $ box files:metadata:delete\n\nEXAMPLES\n  $ box files:metadata:remove 11111 --scope global --template-key properties\n```\n\n## `box files:metadata:get ID`\n\nGet information about a metadata object\n\n```\nUSAGE\n  $ box files:metadata:get ID --template-key <value> [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s\n    | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--scope <value>]\n\nARGUMENTS\n  ID  ID of the file to get metadata on\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to retrieve\n      --template-key=<value>       (required) The key of the metadata template to retrieve\n\nDESCRIPTION\n  Get information about a metadata object\n\nEXAMPLES\n  $ box files:metadata:get 11111 --template-key employeeRecord\n```\n\n_See code: [src/commands/files/metadata/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/metadata/get.js)_\n\n## `box files:metadata:get-all ID`\n\nGet all metadata on a file\n\n```\nUSAGE\n  $ box files:metadata:get-all ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  Id of the file\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get all metadata on a file\n\nALIASES\n  $ box files:metadata:get-all\n\nEXAMPLES\n  $ box files:metadata 11111\n```\n\n## `box files:metadata:remove ID`\n\nDelete metadata from a file\n\n```\nUSAGE\n  $ box files:metadata:remove ID --template-key <value> [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s\n    | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--scope <value>]\n\nARGUMENTS\n  ID  ID of the file to remove metadata from\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to remove\n      --template-key=<value>       (required) The key of the metadata template to remove\n\nDESCRIPTION\n  Delete metadata from a file\n\nALIASES\n  $ box files:metadata:delete\n\nEXAMPLES\n  $ box files:metadata:remove 11111 --scope global --template-key properties\n```\n\n_See code: [src/commands/files/metadata/remove.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/metadata/remove.js)_\n\n## `box files:metadata:set ID`\n\nSet metadata on a file\n\n```\nUSAGE\n  $ box files:metadata:set ID --data <value>... --template-key <value> [-t <value>] [--as-user <value>] [--no-color]\n    [--json | --csv] [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y]\n    [-q] [--scope <value>]\n\nARGUMENTS\n  ID  ID of the file to add metadata to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --data=<value>...            (required) Metadata key and value, in the form \"key=value\".  Note: For float type,\n                                   use \"#\" at the beginning of digits: key2=#1234.50\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to use\n      --template-key=<value>       (required) The key of the metadata template to use\n\nDESCRIPTION\n  Set metadata on a file\n\nEXAMPLES\n  $ box files:metadata:set 11111 --template-key employeeRecord --data \"name=John Doe\" --data department=Sales\n\n  $ box files:metadata:set 22222 --template-key myTemplate --data \"multiselectkey1=[option1A,option1B]\" --data \"multiselectkey2=[option2A]\"\n```\n\n_See code: [src/commands/files/metadata/set.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/metadata/set.js)_\n\n## `box files:metadata:update ID`\n\nUpdate the metadata attached to a file\n\n```\nUSAGE\n  $ box files:metadata:update ID --template-key <value> [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s\n    | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--scope <value>]\n    [-a <value>...] [-c <value>...] [-m <value>...] [--remove <value>...] [--replace <value>...] [-T <value>...]\n\nARGUMENTS\n  ID  ID of the file to update metadata on\n\nFLAGS\n  -T, --test=<value>...            Test that a metadata key contains a specific value; must be in the form key=value\n  -a, --add=<value>...             Add a key to the metadata document; must be in the form key=value\n  -c, --copy=<value>...            Copy a metadata value to another key; must be in the form sourceKey>destinationKey\n  -h, --help                       Show CLI help\n  -m, --move=<value>...            Move a metadata value from one key to another; must be in the form\n                                   sourceKey>destinationKey\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --remove=<value>...          Remove a key from the metadata document\n      --replace=<value>...         Replace the value of an existing metadata key; must be in the form key=value\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to update against\n      --template-key=<value>       (required) The key of the metadata template to update against\n\nDESCRIPTION\n  Update the metadata attached to a file\n\nEXAMPLES\n  $ box files:metadata:update 11111 --template-key employeeRecord --replace department=Finance\n```\n\n_See code: [src/commands/files/metadata/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/metadata/update.js)_\n\n## `box files:move ID PARENTID`\n\nMove a file to a different folder\n\n```\nUSAGE\n  $ box files:move ID PARENTID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--etag <value>]\n\nARGUMENTS\n  ID        ID of the file to move\n  PARENTID  ID of the new parent folder to move the file into\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --etag=<value>               Only move if etag value matches\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Move a file to a different folder\n\nEXAMPLES\n  $ box files:move 11111 22222\n```\n\n_See code: [src/commands/files/move.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/move.js)_\n\n## `box files:rename ID NAME`\n\nRename a file\n\n```\nUSAGE\n  $ box files:rename ID NAME [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--description\n    <value>] [--etag <value>]\n\nARGUMENTS\n  ID    ID of file to rename\n  NAME  New name of file\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --description=<value>        Change the file description\n      --etag=<value>               Only rename if etag value matches\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Rename a file\n\nEXAMPLES\n  $ box files:rename 11111 \"New File Name.pdf\"\n```\n\n_See code: [src/commands/files/rename.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/rename.js)_\n\n## `box files:share ID`\n\nCreate a shared link for a file\n\n```\nUSAGE\n  $ box files:share ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--access <value>] [--password <value>]\n    [--unshared-at <value>] [--can-download] [--vanity-name <value>] [--can-edit]\n\nARGUMENTS\n  ID  ID of the file to share\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --access=<value>             Shared link access level\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-download          Whether the shared link allows downloads\n      --[no-]can-edit              Whether the shared link allows edits. Only Applicable for files.\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --password=<value>           Shared link password\n      --save-to-file-path=<value>  Override default file path to save report\n      --unshared-at=<value>        Time that this link will become disabled. Use s for seconds, m for minutes, h for\n                                   hours, d for days, w for weeks, M for months. For example, 30 seconds is 30s from\n                                   now.\n      --vanity-name=<value>        Defines a custom vanity name to use in the shared link URL. It should be between 12\n                                   and 30 characters. This field can contains only letters, numbers and hyphens.\n\nDESCRIPTION\n  Create a shared link for a file\n\nALIASES\n  $ box files:shared-links:create\n  $ box files:shared-links:update\n\nEXAMPLES\n  $ box files:share 11111 --access company --vanity-name my-custom-name-123\n```\n\n_See code: [src/commands/files/share.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/share.js)_\n\n## `box files:shared-links:create ID`\n\nCreate a shared link for a file\n\n```\nUSAGE\n  $ box files:shared-links:create ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--access <value>] [--password <value>]\n    [--unshared-at <value>] [--can-download] [--vanity-name <value>] [--can-edit]\n\nARGUMENTS\n  ID  ID of the file to share\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --access=<value>             Shared link access level\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-download          Whether the shared link allows downloads\n      --[no-]can-edit              Whether the shared link allows edits. Only Applicable for files.\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --password=<value>           Shared link password\n      --save-to-file-path=<value>  Override default file path to save report\n      --unshared-at=<value>        Time that this link will become disabled. Use s for seconds, m for minutes, h for\n                                   hours, d for days, w for weeks, M for months. For example, 30 seconds is 30s from\n                                   now.\n      --vanity-name=<value>        Defines a custom vanity name to use in the shared link URL. It should be between 12\n                                   and 30 characters. This field can contains only letters, numbers and hyphens.\n\nDESCRIPTION\n  Create a shared link for a file\n\nALIASES\n  $ box files:shared-links:create\n  $ box files:shared-links:update\n\nEXAMPLES\n  $ box files:share 11111 --access company --vanity-name my-custom-name-123\n```\n\n## `box files:shared-links:delete ID`\n\nDelete a shared link for a file\n\n```\nUSAGE\n  $ box files:shared-links:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the file to unshare\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a shared link for a file\n\nALIASES\n  $ box files:shared-links:delete\n\nEXAMPLES\n  $ box files:unshare 11111\n```\n\n## `box files:shared-links:update ID`\n\nCreate a shared link for a file\n\n```\nUSAGE\n  $ box files:shared-links:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--access <value>] [--password <value>]\n    [--unshared-at <value>] [--can-download] [--vanity-name <value>] [--can-edit]\n\nARGUMENTS\n  ID  ID of the file to share\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --access=<value>             Shared link access level\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-download          Whether the shared link allows downloads\n      --[no-]can-edit              Whether the shared link allows edits. Only Applicable for files.\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --password=<value>           Shared link password\n      --save-to-file-path=<value>  Override default file path to save report\n      --unshared-at=<value>        Time that this link will become disabled. Use s for seconds, m for minutes, h for\n                                   hours, d for days, w for weeks, M for months. For example, 30 seconds is 30s from\n                                   now.\n      --vanity-name=<value>        Defines a custom vanity name to use in the shared link URL. It should be between 12\n                                   and 30 characters. This field can contains only letters, numbers and hyphens.\n\nDESCRIPTION\n  Create a shared link for a file\n\nALIASES\n  $ box files:shared-links:create\n  $ box files:shared-links:update\n\nEXAMPLES\n  $ box files:share 11111 --access company --vanity-name my-custom-name-123\n```\n\n## `box files:tasks ID`\n\nList all tasks on this file\n\n```\nUSAGE\n  $ box files:tasks ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of file on which to retrieve tasks\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all tasks on this file\n\nALIASES\n  $ box files:tasks:list\n\nEXAMPLES\n  $ box files:tasks 11111\n```\n\n_See code: [src/commands/files/tasks/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/tasks/index.js)_\n\n## `box files:tasks:list ID`\n\nList all tasks on this file\n\n```\nUSAGE\n  $ box files:tasks:list ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of file on which to retrieve tasks\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all tasks on this file\n\nALIASES\n  $ box files:tasks:list\n\nEXAMPLES\n  $ box files:tasks 11111\n```\n\n## `box files:unlock ID`\n\nUnlock a file\n\n```\nUSAGE\n  $ box files:unlock ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  Id of file to unlock\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Unlock a file\n\nEXAMPLES\n  $ box files:unlock 11111\n```\n\n_See code: [src/commands/files/unlock.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/unlock.js)_\n\n## `box files:unshare ID`\n\nDelete a shared link for a file\n\n```\nUSAGE\n  $ box files:unshare ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the file to unshare\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a shared link for a file\n\nALIASES\n  $ box files:shared-links:delete\n\nEXAMPLES\n  $ box files:unshare 11111\n```\n\n_See code: [src/commands/files/unshare.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/unshare.js)_\n\n## `box files:update ID`\n\nUpdate a file record\n\n```\nUSAGE\n  $ box files:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--name <value>] [--description <value>]\n    [--tags <value>] [--etag <value>] [--disposition-at <value>]\n\nARGUMENTS\n  ID  ID of the file to update\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --description=<value>        New description for the file\n      --disposition-at=<value>     The retention expiration timestamp for the given file. This date cannot be shortened\n                                   once set on a file\n      --etag=<value>               Only apply updates if the ETag value matches\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --name=<value>               New name for the file\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --tags=<value>               Set tags on the file, specified as comma-separated tags\n\nDESCRIPTION\n  Update a file record\n\nEXAMPLES\n  $ box files:update 11111 --name \"New File Name.pdf\"\n```\n\n_See code: [src/commands/files/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/update.js)_\n\n## `box files:update-lock ID`\n\nLock a file\n\n```\nUSAGE\n  $ box files:update-lock ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--expires <value>] [--prevent-download]\n\nARGUMENTS\n  ID  ID of file to lock\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --expires=<value>            Make the lock expire from a timespan set from now. Use s for seconds, m for minutes,\n                                   h for hours, d for days, w for weeks, M for months. For example, 30 seconds is 30s\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --[no-]prevent-download      Prevent download of locked file\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Lock a file\n\nALIASES\n  $ box files:update-lock\n\nEXAMPLES\n  $ box files:lock 11111\n```\n\n## `box files:upload PATH`\n\nUpload a file to a folder. Use --overwrite to automatically replace an existing file with the same name by uploading a new version\n\n```\nUSAGE\n  $ box files:upload PATH [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-p <value>] [-n <value>]\n    [--content-created-at <value>] [--content-modified-at <value>] [--id-only] [--overwrite]\n\nARGUMENTS\n  PATH  Path to the file to be uploaded\n\nFLAGS\n  -h, --help                         Show CLI help\n  -n, --name=<value>                 Provide different name for uploaded file\n  -p, --parent-id=<value>            [default: 0] ID of the parent folder to upload the file to; defaults to the root\n                                     folder\n  -q, --quiet                        Suppress any non-error output to stderr\n  -s, --save                         Save report to default reports folder on disk\n  -t, --token=<value>                Provide a token to perform this call\n  -v, --verbose                      Show verbose output, which can be helpful for debugging\n  -y, --yes                          Automatically respond yes to all confirmation prompts\n      --as-user=<value>              Provide an ID for a user\n      --bulk-file-path=<value>       File path to bulk .csv or .json objects\n      --content-created-at=<value>   The creation date of the file content. Use a timestamp or shorthand syntax 0t, like\n                                     5w for 5 weeks. Not supported with --overwrite\n      --content-modified-at=<value>  The modification date of the file content. Use a timestamp or shorthand syntax 0t,\n                                     like 5w for 5 weeks\n      --csv                          Output formatted CSV\n      --fields=<value>               Comma separated list of fields to show\n      --id-only                      Return only an ID to output from this command\n      --json                         Output formatted JSON\n      --no-color                     Turn off colors for logging\n      --overwrite                    Overwrite the file if it already exists in the destination folder, by uploading a\n                                     new file version\n      --save-to-file-path=<value>    Override default file path to save report\n\nDESCRIPTION\n  Upload a file to a folder. Use --overwrite to automatically replace an existing file with the same name by uploading a\n  new version\n\nEXAMPLES\n  $ box files:upload /path/to/file.pdf --parent-id 22222\n\n  $ box files:upload /path/to/file.pdf --parent-id 22222 --overwrite\n```\n\n_See code: [src/commands/files/upload.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/upload.js)_\n\n## `box files:versions FILEID`\n\nGet a list of file versions\n\n```\nUSAGE\n  $ box files:versions FILEID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  FILEID  ID of file to get versions for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get a list of file versions\n\nALIASES\n  $ box files:versions:list\n\nEXAMPLES\n  $ box files:versions 11111\n```\n\n_See code: [src/commands/files/versions/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/versions/index.js)_\n\n## `box files:versions:delete FILEID FILEVERSIONID`\n\nDelete a file version\n\n```\nUSAGE\n  $ box files:versions:delete FILEID FILEVERSIONID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--etag <value>]\n\nARGUMENTS\n  FILEID         ID of the file to get versions for\n  FILEVERSIONID  ID of the file version to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --etag=<value>               Only delete if etag value matches\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a file version\n\nEXAMPLES\n  $ box files:versions:delete 11111 55555\n```\n\n_See code: [src/commands/files/versions/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/versions/delete.js)_\n\n## `box files:versions:download FILEID FILEVERSIONID`\n\nDownload a specific version of a file\n\n```\nUSAGE\n  $ box files:versions:download FILEID FILEVERSIONID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--destination\n    <value>] [--create-path] [--overwrite] [--save-as <value>]\n\nARGUMENTS\n  FILEID         ID of the file to download\n  FILEVERSIONID  ID of file version to download\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]create-path           Recursively creates a path to a directory if it does not exist\n      --csv                        Output formatted CSV\n      --destination=<value>        The destination folder to write the file to\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --[no-]overwrite             Overwrite a file if it already exists (prevents overwrite prompt)\n      --save-as=<value>            The filename used when saving the file\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Download a specific version of a file\n\nEXAMPLES\n  $ box files:versions:download 11111 55555\n```\n\n_See code: [src/commands/files/versions/download.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/versions/download.js)_\n\n## `box files:versions:list FILEID`\n\nGet a list of file versions\n\n```\nUSAGE\n  $ box files:versions:list FILEID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  FILEID  ID of file to get versions for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get a list of file versions\n\nALIASES\n  $ box files:versions:list\n\nEXAMPLES\n  $ box files:versions 11111\n```\n\n## `box files:versions:promote FILEID FILEVERSIONID`\n\nPromote a file version\n\n```\nUSAGE\n  $ box files:versions:promote FILEID FILEVERSIONID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  FILEID         ID of the file to get versions for\n  FILEVERSIONID  ID of the file version to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Promote a file version\n\nEXAMPLES\n  $ box files:versions:promote 11111 55555\n```\n\n_See code: [src/commands/files/versions/promote.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/versions/promote.js)_\n\n## `box files:versions:upload FILEID PATH`\n\nUpload a new version of a file\n\n```\nUSAGE\n  $ box files:versions:upload FILEID PATH [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n    [--content-modified-at <value>] [-n <value>]\n\nARGUMENTS\n  FILEID  ID of the file to upload a new version of\n  PATH    Local path to the file to upload\n\nFLAGS\n  -h, --help                         Show CLI help\n  -n, --name=<value>                 Provide different name for uploaded file\n  -q, --quiet                        Suppress any non-error output to stderr\n  -s, --save                         Save report to default reports folder on disk\n  -t, --token=<value>                Provide a token to perform this call\n  -v, --verbose                      Show verbose output, which can be helpful for debugging\n  -y, --yes                          Automatically respond yes to all confirmation prompts\n      --as-user=<value>              Provide an ID for a user\n      --bulk-file-path=<value>       File path to bulk .csv or .json objects\n      --content-modified-at=<value>  The last modification date of the file version. Use a timestamp or shorthand syntax\n                                     0t, like 5w for 5 weeks\n      --csv                          Output formatted CSV\n      --fields=<value>               Comma separated list of fields to show\n      --json                         Output formatted JSON\n      --no-color                     Turn off colors for logging\n      --save-to-file-path=<value>    Override default file path to save report\n\nDESCRIPTION\n  Upload a new version of a file\n\nEXAMPLES\n  $ box files:versions:upload 11111 /path/to/file.pdf\n```\n\n_See code: [src/commands/files/versions/upload.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/versions/upload.js)_\n\n## `box files:zip NAME`\n\nCreate a zip of multiple files and folders and download it\n\n```\nUSAGE\n  $ box files:zip NAME --item <value>... [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--destination\n    <value>] [--create-path] [--overwrite]\n\nARGUMENTS\n  NAME  Name of the zip to be created and downloaded\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]create-path           Recursively creates a path to a directory if it does not exist\n      --csv                        Output formatted CSV\n      --destination=<value>        The destination folder to write the zip file to\n      --fields=<value>             Comma separated list of fields to show\n      --item=<value>...            (required) Files or folders to be part of zip in the form type:ID (i.e. file:1374652)\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --[no-]overwrite             Overwrite a zip file if it already exists\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Create a zip of multiple files and folders and download it\n\nEXAMPLES\n  $ box files:zip sample_file.zip --item=file:12421 --item=folder:48291\n```\n\n_See code: [src/commands/files/zip.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/files/zip.js)_\n"
  },
  {
    "path": "docs/folders.md",
    "content": "`box folders`\n=============\n\nManage folders\n\n* [`box folders:collaborations ID`](#box-folderscollaborations-id)\n* [`box folders:collaborations:add ID`](#box-folderscollaborationsadd-id)\n* [`box folders:collaborations:delete ID`](#box-folderscollaborationsdelete-id)\n* [`box folders:collaborations:list ID`](#box-folderscollaborationslist-id)\n* [`box folders:collaborations:update ID`](#box-folderscollaborationsupdate-id)\n* [`box folders:copy ID PARENTID`](#box-folderscopy-id-parentid)\n* [`box folders:create PARENTID NAME`](#box-folderscreate-parentid-name)\n* [`box folders:delete ID`](#box-foldersdelete-id)\n* [`box folders:download ID`](#box-foldersdownload-id)\n* [`box folders:get ID`](#box-foldersget-id)\n* [`box folders:items ID`](#box-foldersitems-id)\n* [`box folders:list-items ID`](#box-folderslist-items-id)\n* [`box folders:locks ID`](#box-folderslocks-id)\n* [`box folders:locks:create ID`](#box-folderslockscreate-id)\n* [`box folders:locks:delete ID`](#box-folderslocksdelete-id)\n* [`box folders:locks:list ID`](#box-folderslockslist-id)\n* [`box folders:metadata ID`](#box-foldersmetadata-id)\n* [`box folders:metadata:add ID`](#box-foldersmetadataadd-id)\n* [`box folders:metadata:create ID`](#box-foldersmetadatacreate-id)\n* [`box folders:metadata:delete ID`](#box-foldersmetadatadelete-id)\n* [`box folders:metadata:get ID`](#box-foldersmetadataget-id)\n* [`box folders:metadata:get-all ID`](#box-foldersmetadataget-all-id)\n* [`box folders:metadata:remove ID`](#box-foldersmetadataremove-id)\n* [`box folders:metadata:set ID`](#box-foldersmetadataset-id)\n* [`box folders:metadata:update ID`](#box-foldersmetadataupdate-id)\n* [`box folders:move ID PARENTID`](#box-foldersmove-id-parentid)\n* [`box folders:rename ID NAME`](#box-foldersrename-id-name)\n* [`box folders:share ID`](#box-foldersshare-id)\n* [`box folders:shared-links:create ID`](#box-foldersshared-linkscreate-id)\n* [`box folders:shared-links:delete ID`](#box-foldersshared-linksdelete-id)\n* [`box folders:shared-links:update ID`](#box-foldersshared-linksupdate-id)\n* [`box folders:unshare ID`](#box-foldersunshare-id)\n* [`box folders:update ID`](#box-foldersupdate-id)\n* [`box folders:upload PATH`](#box-foldersupload-path)\n\n## `box folders:collaborations ID`\n\nList all collaborations on a folder\n\n```\nUSAGE\n  $ box folders:collaborations ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the folder to get the collaborations on\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all collaborations on a folder\n\nALIASES\n  $ box folders:collaborations:list\n\nEXAMPLES\n  $ box folders:collaborations 22222\n```\n\n_See code: [src/commands/folders/collaborations/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/collaborations/index.js)_\n\n## `box folders:collaborations:add ID`\n\nCreate a collaboration for a folder\n\n```\nUSAGE\n  $ box folders:collaborations:add ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-r\n    editor|viewer|previewer|uploader|previewer_uploader|viewer_uploader|co-owner |  |  |  |  |  |  | ] [--user-id\n    <value> | --group-id <value> | --login <value>] [--can-view-path] [--id-only] [--notify]\n\nARGUMENTS\n  ID  ID of the folder to add a collaboration to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -r, --role=<option>              An option to manually enter the role\n                                   <options:\n                                   editor|viewer|previewer|uploader|previewer_uploader|viewer_uploader|co-owner>\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-view-path         Whether view path collaboration feature is enabled or not\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --group-id=<value>           Id for group to collaborate\n      --id-only                    Return only an ID to output from this command\n      --json                       Output formatted JSON\n      --login=<value>              Login for user to collaborate\n      --no-color                   Turn off colors for logging\n      --[no-]notify                All users will receive email notification of the collaboration\n      --save-to-file-path=<value>  Override default file path to save report\n      --user-id=<value>            Id for user to collaborate\n\nDESCRIPTION\n  Create a collaboration for a folder\n\nEXAMPLES\n  $ box folders:collaborations:add 22222 --role editor --user-id 33333\n```\n\n_See code: [src/commands/folders/collaborations/add.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/collaborations/add.js)_\n\n## `box folders:collaborations:delete ID`\n\nRemove a collaboration\n\n```\nUSAGE\n  $ box folders:collaborations:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  The ID of the collaboration to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Remove a collaboration\n\nALIASES\n  $ box files:collaborations:delete\n  $ box folders:collaborations:delete\n\nEXAMPLES\n  $ box collaborations:delete 12345\n```\n\n## `box folders:collaborations:list ID`\n\nList all collaborations on a folder\n\n```\nUSAGE\n  $ box folders:collaborations:list ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the folder to get the collaborations on\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all collaborations on a folder\n\nALIASES\n  $ box folders:collaborations:list\n\nEXAMPLES\n  $ box folders:collaborations 22222\n```\n\n## `box folders:collaborations:update ID`\n\nUpdate a collaboration\n\n```\nUSAGE\n  $ box folders:collaborations:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-r\n    editor|viewer|previewer|uploader|previewer_uploader|viewer_uploader|co-owner|owner |  |  |  |  |  |  |  | ]\n    [--status accepted|pending|rejected] [--can-view-path] [--expires-at <value>]\n\nARGUMENTS\n  ID  The ID of the collaboration to update\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -r, --role=<option>              An option to manually enter the role\n                                   <options:\n                                   editor|viewer|previewer|uploader|previewer_uploader|viewer_uploader|co-owner|owner>\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-view-path         Whether view path collaboration feature is enabled or not\n      --csv                        Output formatted CSV\n      --expires-at=<value>         When the collaboration should expire\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --status=<option>            Update the collaboration status\n                                   <options: accepted|pending|rejected>\n\nDESCRIPTION\n  Update a collaboration\n\nALIASES\n  $ box files:collaborations:update\n  $ box folders:collaborations:update\n\nEXAMPLES\n  $ box collaborations:update 12345 --role viewer\n```\n\n## `box folders:copy ID PARENTID`\n\nCopy a folder to a different folder\n\n```\nUSAGE\n  $ box folders:copy ID PARENTID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--name <value>]\n    [--id-only]\n\nARGUMENTS\n  ID        ID of the folder to copy\n  PARENTID  ID of the new parent folder to copy the folder into\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --id-only                    Return only an ID to output from this command\n      --json                       Output formatted JSON\n      --name=<value>               An optional new name for the folder\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Copy a folder to a different folder\n\nEXAMPLES\n  $ box folders:copy 22222 44444\n```\n\n_See code: [src/commands/folders/copy.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/copy.js)_\n\n## `box folders:create PARENTID NAME`\n\nCreate a new folder\n\n```\nUSAGE\n  $ box folders:create PARENTID NAME [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--id-only]\n\nARGUMENTS\n  PARENTID  ID of parent folder to add new folder to, use '0' for the root folder\n  NAME      Name of new folder\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --id-only                    Return only an ID to output from this command\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Create a new folder\n\nEXAMPLES\n  $ box folders:create 22222 \"New Subfolder\"\n```\n\n_See code: [src/commands/folders/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/create.js)_\n\n## `box folders:delete ID`\n\nDelete a folder\n\n```\nUSAGE\n  $ box folders:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--etag <value>] [-r] [-f]\n\nARGUMENTS\n  ID  ID of the folder to delete\n\nFLAGS\n  -f, --force                      Permanently delete the folder, bypassing the trash\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -r, --recursive                  Delete the folder, even if it still has items in it\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --etag=<value>               Only delete if etag value matches\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a folder\n\nEXAMPLES\n  $ box folders:delete 22222\n```\n\n_See code: [src/commands/folders/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/delete.js)_\n\n## `box folders:download ID`\n\nDownload a folder\n\n```\nUSAGE\n  $ box folders:download ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--destination <value>] [--zip] [--depth\n    <value>] [--create-path] [--overwrite]\n\nARGUMENTS\n  ID  ID of the folder to download\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]create-path           Recursively creates a path to a directory if it does not exist\n      --csv                        Output formatted CSV\n      --depth=<value>              Number of levels deep to recurse when downloading the folder tree\n      --destination=<value>        The destination folder to download the Box folder into\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --[no-]overwrite             [default: true] Overwrite the folder if it already exists.\n      --save-to-file-path=<value>  Override default file path to save report\n      --zip                        Download the folder into a single .zip archive\n\nDESCRIPTION\n  Download a folder\n\nEXAMPLES\n  $ box folders:download 22222\n```\n\n_See code: [src/commands/folders/download.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/download.js)_\n\n## `box folders:get ID`\n\nGet information about a folder\n\n```\nUSAGE\n  $ box folders:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of folder to get; use 0 for the root folder\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a folder\n\nEXAMPLES\n  $ box folders:get 22222\n```\n\n_See code: [src/commands/folders/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/get.js)_\n\n## `box folders:items ID`\n\nList items in a folder\n\n```\nUSAGE\n  $ box folders:items ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--direction\n    ASC|DESC] [--sort id|name|date]\n\nARGUMENTS\n  ID  ID of the folder to get the items in, use 0 for the root folder\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --direction=<option>         The direction to order returned items\n                                   <options: ASC|DESC>\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --sort=<option>              The parameter to sort returned items\n                                   <options: id|name|date>\n\nDESCRIPTION\n  List items in a folder\n\nALIASES\n  $ box folders:list-items\n\nEXAMPLES\n  $ box folders:items 22222\n```\n\n_See code: [src/commands/folders/items.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/items.js)_\n\n## `box folders:list-items ID`\n\nList items in a folder\n\n```\nUSAGE\n  $ box folders:list-items ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--direction\n    ASC|DESC] [--sort id|name|date]\n\nARGUMENTS\n  ID  ID of the folder to get the items in, use 0 for the root folder\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --direction=<option>         The direction to order returned items\n                                   <options: ASC|DESC>\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --sort=<option>              The parameter to sort returned items\n                                   <options: id|name|date>\n\nDESCRIPTION\n  List items in a folder\n\nALIASES\n  $ box folders:list-items\n\nEXAMPLES\n  $ box folders:items 22222\n```\n\n## `box folders:locks ID`\n\nList all locks on a folder\n\n```\nUSAGE\n  $ box folders:locks ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the folder to get the locks on\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all locks on a folder\n\nALIASES\n  $ box folders:locks:list\n\nEXAMPLES\n  $ box folders:locks 22222\n```\n\n_See code: [src/commands/folders/locks/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/locks/index.js)_\n\n## `box folders:locks:create ID`\n\nCreate a lock on a folder\n\n```\nUSAGE\n  $ box folders:locks:create ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the folder to create a lock on\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Create a lock on a folder\n\nEXAMPLES\n  $ box folders:locks:create 22222\n```\n\n_See code: [src/commands/folders/locks/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/locks/create.js)_\n\n## `box folders:locks:delete ID`\n\nDelete a lock on a folder\n\n```\nUSAGE\n  $ box folders:locks:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the folder lock to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a lock on a folder\n\nEXAMPLES\n  $ box folders:locks:delete 22222\n```\n\n_See code: [src/commands/folders/locks/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/locks/delete.js)_\n\n## `box folders:locks:list ID`\n\nList all locks on a folder\n\n```\nUSAGE\n  $ box folders:locks:list ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the folder to get the locks on\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all locks on a folder\n\nALIASES\n  $ box folders:locks:list\n\nEXAMPLES\n  $ box folders:locks 22222\n```\n\n## `box folders:metadata ID`\n\nGet all metadata on a folder\n\n```\nUSAGE\n  $ box folders:metadata ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the folder to get all metadata on\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get all metadata on a folder\n\nALIASES\n  $ box folders:metadata:get-all\n\nEXAMPLES\n  $ box folders:metadata 22222\n```\n\n_See code: [src/commands/folders/metadata/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/metadata/index.js)_\n\n## `box folders:metadata:add ID`\n\nAdd metadata to a folder\n\n```\nUSAGE\n  $ box folders:metadata:add ID --data <value>... --template-key <value> [-t <value>] [--as-user <value>] [--no-color]\n    [--json | --csv] [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y]\n    [-q] [--scope <value>]\n\nARGUMENTS\n  ID  ID of the folder to add metadata to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --data=<value>...            (required) Metadata key and value, in the form \"key=value\".  Note: For float type,\n                                   use \"#\" at the beginning of digits: key2=#1234.50\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to use\n      --template-key=<value>       (required) The key of the metadata template to use\n\nDESCRIPTION\n  Add metadata to a folder\n\nALIASES\n  $ box folders:metadata:create\n\nEXAMPLES\n  $ box folders:metadata:add 22222 --template-key employeeRecord --data \"name=John Doe\" --data department=Sales\n\n  $ box folders:metadata:add 22222 --template-key myTemplate --data \"multiselectkey1=[option1A,option1B]\" --data \"multiselectkey2=[option2A]\"\n```\n\n_See code: [src/commands/folders/metadata/add.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/metadata/add.js)_\n\n## `box folders:metadata:create ID`\n\nAdd metadata to a folder\n\n```\nUSAGE\n  $ box folders:metadata:create ID --data <value>... --template-key <value> [-t <value>] [--as-user <value>] [--no-color]\n    [--json | --csv] [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y]\n    [-q] [--scope <value>]\n\nARGUMENTS\n  ID  ID of the folder to add metadata to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --data=<value>...            (required) Metadata key and value, in the form \"key=value\".  Note: For float type,\n                                   use \"#\" at the beginning of digits: key2=#1234.50\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to use\n      --template-key=<value>       (required) The key of the metadata template to use\n\nDESCRIPTION\n  Add metadata to a folder\n\nALIASES\n  $ box folders:metadata:create\n\nEXAMPLES\n  $ box folders:metadata:add 22222 --template-key employeeRecord --data \"name=John Doe\" --data department=Sales\n\n  $ box folders:metadata:add 22222 --template-key myTemplate --data \"multiselectkey1=[option1A,option1B]\" --data \"multiselectkey2=[option2A]\"\n```\n\n## `box folders:metadata:delete ID`\n\nDelete metadata from a folder\n\n```\nUSAGE\n  $ box folders:metadata:delete ID --template-key <value> [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s\n    | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--scope <value>]\n\nARGUMENTS\n  ID  ID of the folder to remove metadata from\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to remove\n      --template-key=<value>       (required) The key of the metadata template to remove\n\nDESCRIPTION\n  Delete metadata from a folder\n\nALIASES\n  $ box folders:metadata:delete\n\nEXAMPLES\n  $ box folders:metadata:remove 22222 --scope global --template-key properties\n```\n\n## `box folders:metadata:get ID`\n\nGet information about a metadata object\n\n```\nUSAGE\n  $ box folders:metadata:get ID --template-key <value> [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s\n    | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--scope <value>]\n\nARGUMENTS\n  ID  ID of the folder to get metadata on\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to retrieve\n      --template-key=<value>       (required) The key of the metadata template to retrieve\n\nDESCRIPTION\n  Get information about a metadata object\n\nEXAMPLES\n  $ box folders:metadata:get 22222 --template-key employeeRecord\n```\n\n_See code: [src/commands/folders/metadata/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/metadata/get.js)_\n\n## `box folders:metadata:get-all ID`\n\nGet all metadata on a folder\n\n```\nUSAGE\n  $ box folders:metadata:get-all ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the folder to get all metadata on\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get all metadata on a folder\n\nALIASES\n  $ box folders:metadata:get-all\n\nEXAMPLES\n  $ box folders:metadata 22222\n```\n\n## `box folders:metadata:remove ID`\n\nDelete metadata from a folder\n\n```\nUSAGE\n  $ box folders:metadata:remove ID --template-key <value> [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s\n    | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--scope <value>]\n\nARGUMENTS\n  ID  ID of the folder to remove metadata from\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to remove\n      --template-key=<value>       (required) The key of the metadata template to remove\n\nDESCRIPTION\n  Delete metadata from a folder\n\nALIASES\n  $ box folders:metadata:delete\n\nEXAMPLES\n  $ box folders:metadata:remove 22222 --scope global --template-key properties\n```\n\n_See code: [src/commands/folders/metadata/remove.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/metadata/remove.js)_\n\n## `box folders:metadata:set ID`\n\nSet metadata on a folder\n\n```\nUSAGE\n  $ box folders:metadata:set ID --data <value>... --template-key <value> [-t <value>] [--as-user <value>] [--no-color]\n    [--json | --csv] [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y]\n    [-q] [--scope <value>]\n\nARGUMENTS\n  ID  ID of the folder to add metadata to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --data=<value>...            (required) Metadata key and value, in the form \"key=value\".  Note: For float type,\n                                   use \"#\" at the beginning of digits: key2=#1234.50\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to use\n      --template-key=<value>       (required) The key of the metadata template to use\n\nDESCRIPTION\n  Set metadata on a folder\n\nEXAMPLES\n  $ box folders:metadata:set 22222 --template-key employeeRecord --data \"name=John Doe\" --data department=Sales\n\n  $ box folders:metadata:set 22222 --template-key myTemplate --data \"multiselectkey1=[option1A,option1B]\" --data \"multiselectkey2=[option2A]\"\n```\n\n_See code: [src/commands/folders/metadata/set.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/metadata/set.js)_\n\n## `box folders:metadata:update ID`\n\nUpdate the metadata attached to a folder\n\n```\nUSAGE\n  $ box folders:metadata:update ID --template-key <value> [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s\n    | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--scope <value>]\n    [-a <value>...] [-c <value>...] [-m <value>...] [--remove <value>...] [--replace <value>...] [-T <value>...]\n\nARGUMENTS\n  ID  ID of the folder to update metadata on\n\nFLAGS\n  -T, --test=<value>...            Test that a metadata key contains a specific value; must be in the form key=value\n  -a, --add=<value>...             Add a key to the metadata document; must be in the form key=value\n  -c, --copy=<value>...            Copy a metadata value to another key; must be in the form sourceKey>destinationKey\n  -h, --help                       Show CLI help\n  -m, --move=<value>...            Move a metadata value from one key to another; must be in the form\n                                   sourceKey>destinationKey\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --remove=<value>...          Remove a key from the metadata document\n      --replace=<value>...         Replace the value of an existing metadata key; must be in the form key=value\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to update against\n      --template-key=<value>       (required) The key of the metadata template to update against\n\nDESCRIPTION\n  Update the metadata attached to a folder\n\nEXAMPLES\n  $ box folders:metadata:update 22222 --template-key employeeRecord --replace department=Finance\n```\n\n_See code: [src/commands/folders/metadata/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/metadata/update.js)_\n\n## `box folders:move ID PARENTID`\n\nMove a folder to a different folder\n\n```\nUSAGE\n  $ box folders:move ID PARENTID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--etag <value>]\n    [--owned-by <value>]\n\nARGUMENTS\n  ID        ID of folder to copy\n  PARENTID  ID of the new parent folder to move the folder into\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --etag=<value>               Only move if etag value matches\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --owned-by=<value>           ID of the user to own the folder\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Move a folder to a different folder\n\nEXAMPLES\n  $ box folders:move 22222 44444\n```\n\n_See code: [src/commands/folders/move.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/move.js)_\n\n## `box folders:rename ID NAME`\n\nRename a folder\n\n```\nUSAGE\n  $ box folders:rename ID NAME [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--description\n    <value>] [--etag <value>]\n\nARGUMENTS\n  ID    ID of the folder to rename\n  NAME  New name for the folder\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --description=<value>        Change the folder description\n      --etag=<value>               Only rename if etag value matches\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Rename a folder\n\nEXAMPLES\n  $ box folders:rename 22222 \"New Folder Name\"\n```\n\n_See code: [src/commands/folders/rename.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/rename.js)_\n\n## `box folders:share ID`\n\nCreate a shared link for a folder\n\n```\nUSAGE\n  $ box folders:share ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--access <value>] [--password <value>]\n    [--unshared-at <value>] [--can-download] [--vanity-name <value>]\n\nARGUMENTS\n  ID  ID of the folder to share\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --access=<value>             Shared link access level\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-download          Whether the shared link allows downloads\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --password=<value>           Shared link password\n      --save-to-file-path=<value>  Override default file path to save report\n      --unshared-at=<value>        Time that this link will become disabled. Use s for seconds, m for minutes, h for\n                                   hours, d for days, w for weeks, M for months. For example, 30 seconds is 30s from\n                                   now.\n      --vanity-name=<value>        Defines a custom vanity name to use in the shared link URL. It should be between 12\n                                   and 30 characters. This field can contains only letters, numbers and hyphens.\n\nDESCRIPTION\n  Create a shared link for a folder\n\nALIASES\n  $ box folders:shared-links:create\n  $ box folders:shared-links:update\n\nEXAMPLES\n  $ box folders:share 22222 --access company --vanity-name my-custom-name-123\n```\n\n_See code: [src/commands/folders/share.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/share.js)_\n\n## `box folders:shared-links:create ID`\n\nCreate a shared link for a folder\n\n```\nUSAGE\n  $ box folders:shared-links:create ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--access <value>] [--password <value>]\n    [--unshared-at <value>] [--can-download] [--vanity-name <value>]\n\nARGUMENTS\n  ID  ID of the folder to share\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --access=<value>             Shared link access level\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-download          Whether the shared link allows downloads\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --password=<value>           Shared link password\n      --save-to-file-path=<value>  Override default file path to save report\n      --unshared-at=<value>        Time that this link will become disabled. Use s for seconds, m for minutes, h for\n                                   hours, d for days, w for weeks, M for months. For example, 30 seconds is 30s from\n                                   now.\n      --vanity-name=<value>        Defines a custom vanity name to use in the shared link URL. It should be between 12\n                                   and 30 characters. This field can contains only letters, numbers and hyphens.\n\nDESCRIPTION\n  Create a shared link for a folder\n\nALIASES\n  $ box folders:shared-links:create\n  $ box folders:shared-links:update\n\nEXAMPLES\n  $ box folders:share 22222 --access company --vanity-name my-custom-name-123\n```\n\n## `box folders:shared-links:delete ID`\n\nDelete a shared link for a folder\n\n```\nUSAGE\n  $ box folders:shared-links:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the folder to unshare\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a shared link for a folder\n\nALIASES\n  $ box folders:shared-links:delete\n\nEXAMPLES\n  $ box folders:unshare 22222\n```\n\n## `box folders:shared-links:update ID`\n\nCreate a shared link for a folder\n\n```\nUSAGE\n  $ box folders:shared-links:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--access <value>] [--password <value>]\n    [--unshared-at <value>] [--can-download] [--vanity-name <value>]\n\nARGUMENTS\n  ID  ID of the folder to share\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --access=<value>             Shared link access level\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-download          Whether the shared link allows downloads\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --password=<value>           Shared link password\n      --save-to-file-path=<value>  Override default file path to save report\n      --unshared-at=<value>        Time that this link will become disabled. Use s for seconds, m for minutes, h for\n                                   hours, d for days, w for weeks, M for months. For example, 30 seconds is 30s from\n                                   now.\n      --vanity-name=<value>        Defines a custom vanity name to use in the shared link URL. It should be between 12\n                                   and 30 characters. This field can contains only letters, numbers and hyphens.\n\nDESCRIPTION\n  Create a shared link for a folder\n\nALIASES\n  $ box folders:shared-links:create\n  $ box folders:shared-links:update\n\nEXAMPLES\n  $ box folders:share 22222 --access company --vanity-name my-custom-name-123\n```\n\n## `box folders:unshare ID`\n\nDelete a shared link for a folder\n\n```\nUSAGE\n  $ box folders:unshare ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the folder to unshare\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a shared link for a folder\n\nALIASES\n  $ box folders:shared-links:delete\n\nEXAMPLES\n  $ box folders:unshare 22222\n```\n\n_See code: [src/commands/folders/unshare.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/unshare.js)_\n\n## `box folders:update ID`\n\nUpdate a folder\n\n```\nUSAGE\n  $ box folders:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--name <value>]\n    [--can-non-owners-invite] [--can-non-owners-view-collaborators] [--description <value>] [--upload-email-access\n    open|collaborators] [--tags <value>] [--sync] [--restrict-collaboration] [--restrict-to-enterprise] [--etag <value>]\n\nARGUMENTS\n  ID  ID of the folder to update\n\nFLAGS\n  -h, --help                                    Show CLI help\n  -q, --quiet                                   Suppress any non-error output to stderr\n  -s, --save                                    Save report to default reports folder on disk\n  -t, --token=<value>                           Provide a token to perform this call\n  -v, --verbose                                 Show verbose output, which can be helpful for debugging\n  -y, --yes                                     Automatically respond yes to all confirmation prompts\n      --as-user=<value>                         Provide an ID for a user\n      --bulk-file-path=<value>                  File path to bulk .csv or .json objects\n      --[no-]can-non-owners-invite              Specifies if users who are not the owner of the folder can invite new\n                                                collaborators to the folder.\n      --[no-]can-non-owners-view-collaborators  Restricts collaborators who are not the owner of this folder from\n                                                viewing other collaborations on this folder.\n      --csv                                     Output formatted CSV\n      --description=<value>                     New description for folder\n      --etag=<value>                            Only apply updates if the etag value matches\n      --fields=<value>                          Comma separated list of fields to show\n      --json                                    Output formatted JSON\n      --name=<value>                            New name for folder\n      --no-color                                Turn off colors for logging\n      --[no-]restrict-collaboration             Restrict collaboration so only owners can invite new collaborators\n      --[no-]restrict-to-enterprise             Restrict collaboration so only users in the folder owner's enterprise\n                                                can be added\n      --save-to-file-path=<value>               Override default file path to save report\n      --[no-]sync                               Whether the folder is synced to desktop\n      --tags=<value>                            Comma seperated tags\n      --upload-email-access=<option>            Upload email access level\n                                                <options: open|collaborators>\n\nDESCRIPTION\n  Update a folder\n\nEXAMPLES\n  $ box folders:update 22222 --name \"New Folder Name\"\n```\n\n_See code: [src/commands/folders/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/update.js)_\n\n## `box folders:upload PATH`\n\nUpload a folder\n\n```\nUSAGE\n  $ box folders:upload PATH [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--folder-name <value>] [--id-only] [-p\n    <value>]\n\nARGUMENTS\n  PATH  Local path to the folder to upload\n\nFLAGS\n  -h, --help                       Show CLI help\n  -p, --parent-folder=<value>      [default: 0] Folder to upload this folder into; defaults to the root folder\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --folder-name=<value>        Name to use for folder if not using local folder name\n      --id-only                    Return only an ID to output from this command\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Upload a folder\n\nEXAMPLES\n  $ box folders:upload /path/to/folder\n```\n\n_See code: [src/commands/folders/upload.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/folders/upload.js)_\n"
  },
  {
    "path": "docs/groups.md",
    "content": "`box groups`\n============\n\nList all groups\n\n* [`box groups`](#box-groups)\n* [`box groups:collaborations ID`](#box-groupscollaborations-id)\n* [`box groups:create NAME`](#box-groupscreate-name)\n* [`box groups:delete ID`](#box-groupsdelete-id)\n* [`box groups:get ID`](#box-groupsget-id)\n* [`box groups:list`](#box-groupslist)\n* [`box groups:list-collaborations ID`](#box-groupslist-collaborations-id)\n* [`box groups:membership:add USERID GROUPID`](#box-groupsmembershipadd-userid-groupid)\n* [`box groups:membership:get ID`](#box-groupsmembershipget-id)\n* [`box groups:membership:list ID`](#box-groupsmembershiplist-id)\n* [`box groups:membership:remove ID`](#box-groupsmembershipremove-id)\n* [`box groups:membership:update ID`](#box-groupsmembershipupdate-id)\n* [`box groups:memberships ID`](#box-groupsmemberships-id)\n* [`box groups:memberships:add USERID GROUPID`](#box-groupsmembershipsadd-userid-groupid)\n* [`box groups:memberships:get ID`](#box-groupsmembershipsget-id)\n* [`box groups:memberships:remove ID`](#box-groupsmembershipsremove-id)\n* [`box groups:memberships:update ID`](#box-groupsmembershipsupdate-id)\n* [`box groups:terminate-session`](#box-groupsterminate-session)\n* [`box groups:update ID`](#box-groupsupdate-id)\n\n## `box groups`\n\nList all groups\n\n```\nUSAGE\n  $ box groups [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--filter <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --filter=<value>             Search term to filter groups on; matches prefixes of group name\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all groups\n\nALIASES\n  $ box groups:list\n\nEXAMPLES\n  $ box groups\n```\n\n_See code: [src/commands/groups/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/groups/index.js)_\n\n## `box groups:collaborations ID`\n\nList collaborations for a group\n\n```\nUSAGE\n  $ box groups:collaborations ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the group to get collaborations for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List collaborations for a group\n\nALIASES\n  $ box groups:list-collaborations\n  $ box collaborations:list-for-group\n\nEXAMPLES\n  $ box groups:collaborations 12345\n```\n\n_See code: [src/commands/groups/collaborations.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/groups/collaborations.js)_\n\n## `box groups:create NAME`\n\nCreate a group\n\n```\nUSAGE\n  $ box groups:create NAME [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--description <value>]\n    [--external-sync-identifier <value>] [--provenance <value>] [-i admins_only|admins_and_members|all_managed_users]\n    [-m admins_only|admins_and_members|all_managed_users] [--id-only]\n\nARGUMENTS\n  NAME  Group name\n\nFLAGS\n  -h, --help                              Show CLI help\n  -i, --invite=<option>                   Specifies who can invite the group to collaborate\n                                          <options: admins_only|admins_and_members|all_managed_users>\n  -m, --view-members=<option>             Specifies who can view the members of the group\n                                          <options: admins_only|admins_and_members|all_managed_users>\n  -q, --quiet                             Suppress any non-error output to stderr\n  -s, --save                              Save report to default reports folder on disk\n  -t, --token=<value>                     Provide a token to perform this call\n  -v, --verbose                           Show verbose output, which can be helpful for debugging\n  -y, --yes                               Automatically respond yes to all confirmation prompts\n      --as-user=<value>                   Provide an ID for a user\n      --bulk-file-path=<value>            File path to bulk .csv or .json objects\n      --csv                               Output formatted CSV\n      --description=<value>               Description of the group\n      --external-sync-identifier=<value>  Group identifier for groups coming from an external source\n      --fields=<value>                    Comma separated list of fields to show\n      --id-only                           Return only an ID to output from this command\n      --json                              Output formatted JSON\n      --no-color                          Turn off colors for logging\n      --provenance=<value>                Track the external source where the group is coming from\n      --save-to-file-path=<value>         Override default file path to save report\n\nDESCRIPTION\n  Create a group\n\nEXAMPLES\n  $ box groups:create \"US Employees\"\n```\n\n_See code: [src/commands/groups/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/groups/create.js)_\n\n## `box groups:delete ID`\n\nDelete a group\n\n```\nUSAGE\n  $ box groups:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the group to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a group\n\nEXAMPLES\n  $ box groups:delete 12345\n```\n\n_See code: [src/commands/groups/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/groups/delete.js)_\n\n## `box groups:get ID`\n\nGet information about a group\n\n```\nUSAGE\n  $ box groups:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the group to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a group\n\nEXAMPLES\n  $ box groups:get 12345\n```\n\n_See code: [src/commands/groups/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/groups/get.js)_\n\n## `box groups:list`\n\nList all groups\n\n```\nUSAGE\n  $ box groups:list [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--filter <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --filter=<value>             Search term to filter groups on; matches prefixes of group name\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all groups\n\nALIASES\n  $ box groups:list\n\nEXAMPLES\n  $ box groups\n```\n\n## `box groups:list-collaborations ID`\n\nList collaborations for a group\n\n```\nUSAGE\n  $ box groups:list-collaborations ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the group to get collaborations for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List collaborations for a group\n\nALIASES\n  $ box groups:list-collaborations\n  $ box collaborations:list-for-group\n\nEXAMPLES\n  $ box groups:collaborations 12345\n```\n\n## `box groups:membership:add USERID GROUPID`\n\nAdd a user to a group\n\n```\nUSAGE\n  $ box groups:membership:add USERID GROUPID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-r member|admin]\n    [--can-run-reports] [--can-instant-login] [--can-create-accounts] [--can-edit-accounts]\n\nARGUMENTS\n  USERID   ID of the user to add to the group\n  GROUPID  ID of the group to add the user to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -r, --role=<option>              [default: member] Set the user's role in the group\n                                   <options: member|admin>\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-create-accounts   If the user is a group admin, allow them to create new users\n      --[no-]can-edit-accounts     If the user is a group admin, allow them to edit user accounts\n      --[no-]can-instant-login     If the user is a group admin, allow them to instant login\n      --[no-]can-run-reports       If the user is a group admin, allow them to run reports\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Add a user to a group\n\nALIASES\n  $ box groups:membership:add\n\nEXAMPLES\n  $ box groups:memberships:add 33333 12345\n```\n\n## `box groups:membership:get ID`\n\nGet information about a group membership\n\n```\nUSAGE\n  $ box groups:membership:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the group membership to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a group membership\n\nALIASES\n  $ box groups:membership:get\n\nEXAMPLES\n  $ box groups:memberships:get 12345\n```\n\n## `box groups:membership:list ID`\n\nList members of a group\n\n```\nUSAGE\n  $ box groups:membership:list ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  ID  ID of the group to get memberships for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List members of a group\n\nALIASES\n  $ box groups:membership:list\n\nEXAMPLES\n  $ box groups:memberships 12345\n```\n\n## `box groups:membership:remove ID`\n\nRemove a user from a group\n\n```\nUSAGE\n  $ box groups:membership:remove ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the group membership record to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Remove a user from a group\n\nALIASES\n  $ box groups:membership:remove\n\nEXAMPLES\n  $ box groups:memberships:remove 12345\n```\n\n## `box groups:membership:update ID`\n\nUpdate a user's membership to a group\n\n```\nUSAGE\n  $ box groups:membership:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-r member|admin |  | ]\n    [--can-run-reports] [--can-instant-login] [--can-create-accounts] [--can-edit-accounts]\n\nARGUMENTS\n  ID  ID of the group membership to update\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -r, --role=<option>              Set the user's role in the group\n                                   <options: member|admin>\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-create-accounts   If the user is a group admin, allow them to create new users\n      --[no-]can-edit-accounts     If the user is a group admin, allow them to edit user accounts\n      --[no-]can-instant-login     If the user is a group admin, allow them to instant login\n      --[no-]can-run-reports       If the user is a group admin, allow them to run reports\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Update a user's membership to a group\n\nALIASES\n  $ box groups:membership:update\n\nEXAMPLES\n  $ box groups:memberships:update\n```\n\n## `box groups:memberships ID`\n\nList members of a group\n\n```\nUSAGE\n  $ box groups:memberships ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  ID  ID of the group to get memberships for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List members of a group\n\nALIASES\n  $ box groups:membership:list\n\nEXAMPLES\n  $ box groups:memberships 12345\n```\n\n_See code: [src/commands/groups/memberships/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/groups/memberships/index.js)_\n\n## `box groups:memberships:add USERID GROUPID`\n\nAdd a user to a group\n\n```\nUSAGE\n  $ box groups:memberships:add USERID GROUPID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-r member|admin]\n    [--can-run-reports] [--can-instant-login] [--can-create-accounts] [--can-edit-accounts]\n\nARGUMENTS\n  USERID   ID of the user to add to the group\n  GROUPID  ID of the group to add the user to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -r, --role=<option>              [default: member] Set the user's role in the group\n                                   <options: member|admin>\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-create-accounts   If the user is a group admin, allow them to create new users\n      --[no-]can-edit-accounts     If the user is a group admin, allow them to edit user accounts\n      --[no-]can-instant-login     If the user is a group admin, allow them to instant login\n      --[no-]can-run-reports       If the user is a group admin, allow them to run reports\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Add a user to a group\n\nALIASES\n  $ box groups:membership:add\n\nEXAMPLES\n  $ box groups:memberships:add 33333 12345\n```\n\n_See code: [src/commands/groups/memberships/add.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/groups/memberships/add.js)_\n\n## `box groups:memberships:get ID`\n\nGet information about a group membership\n\n```\nUSAGE\n  $ box groups:memberships:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the group membership to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a group membership\n\nALIASES\n  $ box groups:membership:get\n\nEXAMPLES\n  $ box groups:memberships:get 12345\n```\n\n_See code: [src/commands/groups/memberships/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/groups/memberships/get.js)_\n\n## `box groups:memberships:remove ID`\n\nRemove a user from a group\n\n```\nUSAGE\n  $ box groups:memberships:remove ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the group membership record to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Remove a user from a group\n\nALIASES\n  $ box groups:membership:remove\n\nEXAMPLES\n  $ box groups:memberships:remove 12345\n```\n\n_See code: [src/commands/groups/memberships/remove.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/groups/memberships/remove.js)_\n\n## `box groups:memberships:update ID`\n\nUpdate a user's membership to a group\n\n```\nUSAGE\n  $ box groups:memberships:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-r member|admin |  | ]\n    [--can-run-reports] [--can-instant-login] [--can-create-accounts] [--can-edit-accounts]\n\nARGUMENTS\n  ID  ID of the group membership to update\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -r, --role=<option>              Set the user's role in the group\n                                   <options: member|admin>\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-create-accounts   If the user is a group admin, allow them to create new users\n      --[no-]can-edit-accounts     If the user is a group admin, allow them to edit user accounts\n      --[no-]can-instant-login     If the user is a group admin, allow them to instant login\n      --[no-]can-run-reports       If the user is a group admin, allow them to run reports\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Update a user's membership to a group\n\nALIASES\n  $ box groups:membership:update\n\nEXAMPLES\n  $ box groups:memberships:update\n```\n\n_See code: [src/commands/groups/memberships/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/groups/memberships/update.js)_\n\n## `box groups:terminate-session`\n\nValidates the roles and permissions of the group, and creates asynchronous jobs to terminate the group's sessions.\n\n```\nUSAGE\n  $ box groups:terminate-session --group-ids <value>... [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --group-ids=<value>...       (required) A list of group IDs\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Validates the roles and permissions of the group, and creates asynchronous jobs to terminate the group's sessions.\n\nEXAMPLES\n  $ box groups:terminate-session --group-ids 123 345\n```\n\n_See code: [src/commands/groups/terminate-session.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/groups/terminate-session.js)_\n\n## `box groups:update ID`\n\nUpdate a group\n\n```\nUSAGE\n  $ box groups:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-n <value>] [--description <value>]\n    [--external-sync-identifier <value>] [--provenance <value>] [-i admins_only|admins_and_members|all_managed_users]\n    [-m admins_only|admins_and_members|all_managed_users]\n\nARGUMENTS\n  ID  ID of the group to update\n\nFLAGS\n  -h, --help                              Show CLI help\n  -i, --invite=<option>                   Specifies who can invite the group to collaborate\n                                          <options: admins_only|admins_and_members|all_managed_users>\n  -m, --view-members=<option>             Specifies who can view the members of the group\n                                          <options: admins_only|admins_and_members|all_managed_users>\n  -n, --name=<value>                      The name of the group\n  -q, --quiet                             Suppress any non-error output to stderr\n  -s, --save                              Save report to default reports folder on disk\n  -t, --token=<value>                     Provide a token to perform this call\n  -v, --verbose                           Show verbose output, which can be helpful for debugging\n  -y, --yes                               Automatically respond yes to all confirmation prompts\n      --as-user=<value>                   Provide an ID for a user\n      --bulk-file-path=<value>            File path to bulk .csv or .json objects\n      --csv                               Output formatted CSV\n      --description=<value>               Description of the group\n      --external-sync-identifier=<value>  group identifier for groups coming from an external source\n      --fields=<value>                    Comma separated list of fields to show\n      --json                              Output formatted JSON\n      --no-color                          Turn off colors for logging\n      --provenance=<value>                Track the external source where the group is coming from\n      --save-to-file-path=<value>         Override default file path to save report\n\nDESCRIPTION\n  Update a group\n\nEXAMPLES\n  $ box groups:update 12345 --name \"U.S. Employees\"\n```\n\n_See code: [src/commands/groups/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/groups/update.js)_\n"
  },
  {
    "path": "docs/help.md",
    "content": "`box help`\n==========\n\nDisplay help for the Box CLI\n\n* [`box help [COMMAND]`](#box-help-command)\n\n## `box help [COMMAND]`\n\nDisplay help for box.\n\n```\nUSAGE\n  $ box help [COMMAND...] [-n]\n\nARGUMENTS\n  [COMMAND...]  Command to show help for.\n\nFLAGS\n  -n, --nested-commands  Include all nested commands in the output.\n\nDESCRIPTION\n  Display help for box.\n```\n\n_See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.36/src/commands/help.js)_\n"
  },
  {
    "path": "docs/hubs.md",
    "content": "`box hubs`\n==========\n\nList Box Hubs for the current user\n\n* [`box hubs`](#box-hubs)\n* [`box hubs:collaborations ID`](#box-hubscollaborations-id)\n* [`box hubs:collaborations:add ID`](#box-hubscollaborationsadd-id)\n* [`box hubs:collaborations:create ID`](#box-hubscollaborationscreate-id)\n* [`box hubs:collaborations:delete ID`](#box-hubscollaborationsdelete-id)\n* [`box hubs:collaborations:get ID`](#box-hubscollaborationsget-id)\n* [`box hubs:collaborations:list ID`](#box-hubscollaborationslist-id)\n* [`box hubs:collaborations:update ID`](#box-hubscollaborationsupdate-id)\n* [`box hubs:copy ID`](#box-hubscopy-id)\n* [`box hubs:create TITLE`](#box-hubscreate-title)\n* [`box hubs:delete ID`](#box-hubsdelete-id)\n* [`box hubs:document:blocks ID PAGEID`](#box-hubsdocumentblocks-id-pageid)\n* [`box hubs:document:blocks:list ID PAGEID`](#box-hubsdocumentblockslist-id-pageid)\n* [`box hubs:document:pages ID`](#box-hubsdocumentpages-id)\n* [`box hubs:document:pages:list ID`](#box-hubsdocumentpageslist-id)\n* [`box hubs:enterprise`](#box-hubsenterprise)\n* [`box hubs:get ID`](#box-hubsget-id)\n* [`box hubs:items ID`](#box-hubsitems-id)\n* [`box hubs:items:list ID`](#box-hubsitemslist-id)\n* [`box hubs:items:manage ID`](#box-hubsitemsmanage-id)\n* [`box hubs:list`](#box-hubslist)\n* [`box hubs:update ID`](#box-hubsupdate-id)\n\n## `box hubs`\n\nList Box Hubs for the current user\n\n```\nUSAGE\n  $ box hubs [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--query <value>]\n    [--scope editable|view_only|all] [--sort name|updated_at|last_accessed_at|view_count|relevance] [--direction\n    ASC|DESC]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --direction=<option>         Sort direction. One of: ASC, DESC\n                                   <options: ASC|DESC>\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --query=<value>              Search query for Box Hubs\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<option>             Scope of hubs to retrieve. One of: editable, view_only, all\n                                   <options: editable|view_only|all>\n      --sort=<option>              Sort field for hubs. One of: name, updated_at, last_accessed_at, view_count,\n                                   relevance\n                                   <options: name|updated_at|last_accessed_at|view_count|relevance>\n\nDESCRIPTION\n  List Box Hubs for the current user\n\nALIASES\n  $ box hubs:list\n\nEXAMPLES\n  $ box hubs\n\n  $ box hubs --query \"Product\" --scope editable --sort name --direction ASC\n```\n\n_See code: [src/commands/hubs/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/hubs/index.js)_\n\n## `box hubs:collaborations ID`\n\nList collaborations for a Box Hub\n\n```\nUSAGE\n  $ box hubs:collaborations ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  ID  ID of the Box Hub\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List collaborations for a Box Hub\n\nALIASES\n  $ box hubs:collaborations:list\n\nEXAMPLES\n  $ box hubs:collaborations 12345\n\n  $ box hubs:collaborations 12345 --max-items 50\n```\n\n_See code: [src/commands/hubs/collaborations/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/hubs/collaborations/index.js)_\n\n## `box hubs:collaborations:add ID`\n\nAdds a collaboration with a specific role for a single user or a single group to a Box Hub. Collaborations can be created using email address, user IDs, or group IDs\n\n```\nUSAGE\n  $ box hubs:collaborations:add ID -r editor|viewer|co-owner [-t <value>] [--as-user <value>] [--no-color] [--json | --csv]\n    [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--user-id\n    <value> | --group-id <value> | --login <value>]\n\nARGUMENTS\n  ID  ID of the Box Hub\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -r, --role=<option>              (required) Role to grant for the hub collaboration. One of: editor, viewer, co-owner\n                                   <options: editor|viewer|co-owner>\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --group-id=<value>           Collaborate a group by Box group ID\n      --json                       Output formatted JSON\n      --login=<value>              Collaborate a user by email address\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --user-id=<value>            Collaborate a user by Box user ID\n\nDESCRIPTION\n  Adds a collaboration with a specific role for a single user or a single group to a Box Hub. Collaborations can be\n  created using email address, user IDs, or group IDs\n\nALIASES\n  $ box hubs:collaborations:add\n\nEXAMPLES\n  $ box hubs:collaborations:create 12345 --role editor --user-id 22222\n\n  $ box hubs:collaborations:create 12345 --role viewer --group-id 33333\n\n  $ box hubs:collaborations:create 12345 --role co-owner --login jdoe@example.com\n```\n\n## `box hubs:collaborations:create ID`\n\nAdds a collaboration with a specific role for a single user or a single group to a Box Hub. Collaborations can be created using email address, user IDs, or group IDs\n\n```\nUSAGE\n  $ box hubs:collaborations:create ID -r editor|viewer|co-owner [-t <value>] [--as-user <value>] [--no-color] [--json | --csv]\n    [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--user-id\n    <value> | --group-id <value> | --login <value>]\n\nARGUMENTS\n  ID  ID of the Box Hub\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -r, --role=<option>              (required) Role to grant for the hub collaboration. One of: editor, viewer, co-owner\n                                   <options: editor|viewer|co-owner>\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --group-id=<value>           Collaborate a group by Box group ID\n      --json                       Output formatted JSON\n      --login=<value>              Collaborate a user by email address\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --user-id=<value>            Collaborate a user by Box user ID\n\nDESCRIPTION\n  Adds a collaboration with a specific role for a single user or a single group to a Box Hub. Collaborations can be\n  created using email address, user IDs, or group IDs\n\nALIASES\n  $ box hubs:collaborations:add\n\nEXAMPLES\n  $ box hubs:collaborations:create 12345 --role editor --user-id 22222\n\n  $ box hubs:collaborations:create 12345 --role viewer --group-id 33333\n\n  $ box hubs:collaborations:create 12345 --role co-owner --login jdoe@example.com\n```\n\n_See code: [src/commands/hubs/collaborations/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/hubs/collaborations/create.js)_\n\n## `box hubs:collaborations:delete ID`\n\nDelete a single Box Hub collaboration\n\n```\nUSAGE\n  $ box hubs:collaborations:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the hub collaboration to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a single Box Hub collaboration\n\nEXAMPLES\n  $ box hubs:collaborations:delete 99999\n```\n\n_See code: [src/commands/hubs/collaborations/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/hubs/collaborations/delete.js)_\n\n## `box hubs:collaborations:get ID`\n\nRetrieves details for a Box Hub collaboration by collaboration ID\n\n```\nUSAGE\n  $ box hubs:collaborations:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the hub collaboration\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Retrieves details for a Box Hub collaboration by collaboration ID\n\nEXAMPLES\n  $ box hubs:collaborations:get 99999\n```\n\n_See code: [src/commands/hubs/collaborations/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/hubs/collaborations/get.js)_\n\n## `box hubs:collaborations:list ID`\n\nList collaborations for a Box Hub\n\n```\nUSAGE\n  $ box hubs:collaborations:list ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  ID  ID of the Box Hub\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List collaborations for a Box Hub\n\nALIASES\n  $ box hubs:collaborations:list\n\nEXAMPLES\n  $ box hubs:collaborations 12345\n\n  $ box hubs:collaborations 12345 --max-items 50\n```\n\n## `box hubs:collaborations:update ID`\n\nUpdates a Box Hub collaboration. Can be used to change the Box Hub role.\n\n```\nUSAGE\n  $ box hubs:collaborations:update ID -r editor|viewer|co-owner [-t <value>] [--as-user <value>] [--no-color] [--json | --csv]\n    [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the hub collaboration to update\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -r, --role=<option>              (required) Updated role for the hub collaboration. One of: editor, viewer, co-owner\n                                   <options: editor|viewer|co-owner>\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Updates a Box Hub collaboration. Can be used to change the Box Hub role.\n\nEXAMPLES\n  $ box hubs:collaborations:update 99999 --role viewer\n```\n\n_See code: [src/commands/hubs/collaborations/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/hubs/collaborations/update.js)_\n\n## `box hubs:copy ID`\n\nCopy a Box Hub\n\n```\nUSAGE\n  $ box hubs:copy ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-T <value>] [-d <value>]\n\nARGUMENTS\n  ID  ID of the Box Hub to copy\n\nFLAGS\n  -T, --title=<value>              Optional title override for the copied hub\n  -d, --description=<value>        Optional description override for the copied hub\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Copy a Box Hub\n\nEXAMPLES\n  $ box hubs:copy 12345 --title \"Copied hub title\" --description \"Copied hub description\"\n```\n\n_See code: [src/commands/hubs/copy.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/hubs/copy.js)_\n\n## `box hubs:create TITLE`\n\nCreate a new Box Hub\n\n```\nUSAGE\n  $ box hubs:create TITLE [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-d <value>]\n\nARGUMENTS\n  TITLE  Title for the Box Hub\n\nFLAGS\n  -d, --description=<value>        Description of the Box Hub\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Create a new Box Hub\n\nEXAMPLES\n  $ box hubs:create \"Roadmap Hub\" --description \"Q3 planning hub\"\n```\n\n_See code: [src/commands/hubs/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/hubs/create.js)_\n\n## `box hubs:delete ID`\n\nDelete a Box Hub\n\n```\nUSAGE\n  $ box hubs:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the Box Hub to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a Box Hub\n\nEXAMPLES\n  $ box hubs:delete 12345\n```\n\n_See code: [src/commands/hubs/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/hubs/delete.js)_\n\n## `box hubs:document:blocks ID PAGEID`\n\nRetrieve sorted Hub Document Blocks for a specific hub document page, excluding items. Results are organized by parent_id and include only blocks on that page, not sub pages or their content blocks.\n\n```\nUSAGE\n  $ box hubs:document:blocks ID PAGEID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  ID      ID of the Box Hub\n  PAGEID  ID of the page in the Box Hub document\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Retrieve sorted Hub Document Blocks for a specific hub document page, excluding items. Results are organized by\n  parent_id and include only blocks on that page, not sub pages or their content blocks.\n\nALIASES\n  $ box hubs:document:blocks:list\n\nEXAMPLES\n  $ box hubs:document:blocks 12345 55c8361a-012a-4fa1-a724-b7ef1cd87865\n\n  $ box hubs:document:blocks 12345 55c8361a-012a-4fa1-a724-b7ef1cd87865 --max-items 50\n```\n\n_See code: [src/commands/hubs/document/blocks.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/hubs/document/blocks.js)_\n\n## `box hubs:document:blocks:list ID PAGEID`\n\nRetrieve sorted Hub Document Blocks for a specific hub document page, excluding items. Results are organized by parent_id and include only blocks on that page, not sub pages or their content blocks.\n\n```\nUSAGE\n  $ box hubs:document:blocks:list ID PAGEID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  ID      ID of the Box Hub\n  PAGEID  ID of the page in the Box Hub document\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Retrieve sorted Hub Document Blocks for a specific hub document page, excluding items. Results are organized by\n  parent_id and include only blocks on that page, not sub pages or their content blocks.\n\nALIASES\n  $ box hubs:document:blocks:list\n\nEXAMPLES\n  $ box hubs:document:blocks 12345 55c8361a-012a-4fa1-a724-b7ef1cd87865\n\n  $ box hubs:document:blocks 12345 55c8361a-012a-4fa1-a724-b7ef1cd87865 --max-items 50\n```\n\n## `box hubs:document:pages ID`\n\nRetrieves a list of Hub Document Pages for the specified hub. Includes both root-level pages and sub pages\n\n```\nUSAGE\n  $ box hubs:document:pages ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  ID  ID of the Box Hub\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Retrieves a list of Hub Document Pages for the specified hub. Includes both root-level pages and sub pages\n\nALIASES\n  $ box hubs:document:pages:list\n\nEXAMPLES\n  $ box hubs:document:pages 12345\n\n  $ box hubs:document:pages 12345 --max-items 50\n```\n\n_See code: [src/commands/hubs/document/pages.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/hubs/document/pages.js)_\n\n## `box hubs:document:pages:list ID`\n\nRetrieves a list of Hub Document Pages for the specified hub. Includes both root-level pages and sub pages\n\n```\nUSAGE\n  $ box hubs:document:pages:list ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  ID  ID of the Box Hub\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Retrieves a list of Hub Document Pages for the specified hub. Includes both root-level pages and sub pages\n\nALIASES\n  $ box hubs:document:pages:list\n\nEXAMPLES\n  $ box hubs:document:pages 12345\n\n  $ box hubs:document:pages 12345 --max-items 50\n```\n\n## `box hubs:enterprise`\n\nList Box Hubs across the enterprise. This call requires an admin or hub co-admin of an enterprise with GCM scope. Otherwise, Box returns a 403 status code with the message `The request requires higher privileges than provided by the access token.` See https://developer.box.com/guides/api-calls/permissions-and-errors/scopes#global-content-manager-gcm\n\n```\nUSAGE\n  $ box hubs:enterprise [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--query <value>]\n    [--sort name|updated_at|last_accessed_at|view_count|relevance] [--direction ASC|DESC]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --direction=<option>         Sort direction. One of: ASC, DESC\n                                   <options: ASC|DESC>\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --query=<value>              Search query for enterprise Box Hubs\n      --save-to-file-path=<value>  Override default file path to save report\n      --sort=<option>              Sort field for hubs. One of: name, updated_at, last_accessed_at, view_count,\n                                   relevance\n                                   <options: name|updated_at|last_accessed_at|view_count|relevance>\n\nDESCRIPTION\n  List Box Hubs across the enterprise. This call requires an admin or hub co-admin of an enterprise with GCM scope.\n  Otherwise, Box returns a 403 status code with the message `The request requires higher privileges than provided by the\n  access token.` See https://developer.box.com/guides/api-calls/permissions-and-errors/scopes#global-content-manager-gcm\n\nEXAMPLES\n  $ box hubs:enterprise\n\n  $ box hubs:enterprise --query \"Roadmap\" --sort updated_at --direction DESC\n```\n\n_See code: [src/commands/hubs/enterprise.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/hubs/enterprise.js)_\n\n## `box hubs:get ID`\n\nGet details for a Box Hub\n\n```\nUSAGE\n  $ box hubs:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the Box Hub\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get details for a Box Hub\n\nEXAMPLES\n  $ box hubs:get 12345\n```\n\n_See code: [src/commands/hubs/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/hubs/get.js)_\n\n## `box hubs:items ID`\n\nList items in a Box Hub\n\n```\nUSAGE\n  $ box hubs:items ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--parent-id\n    <value>]\n\nARGUMENTS\n  ID  ID of the Box Hub\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --parent-id=<value>          Filter to items that belong to a specific item list block in the Box Hub\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List items in a Box Hub\n\nALIASES\n  $ box hubs:items:list\n\nEXAMPLES\n  $ box hubs:items 12345\n\n  $ box hubs:items 12345 --parent-id 67890 --max-items 50\n```\n\n_See code: [src/commands/hubs/items/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/hubs/items/index.js)_\n\n## `box hubs:items:list ID`\n\nList items in a Box Hub\n\n```\nUSAGE\n  $ box hubs:items:list ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--parent-id\n    <value>]\n\nARGUMENTS\n  ID  ID of the Box Hub\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --parent-id=<value>          Filter to items that belong to a specific item list block in the Box Hub\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List items in a Box Hub\n\nALIASES\n  $ box hubs:items:list\n\nEXAMPLES\n  $ box hubs:items 12345\n\n  $ box hubs:items 12345 --parent-id 67890 --max-items 50\n```\n\n## `box hubs:items:manage ID`\n\nAdd or remove items in a Box Hub\n\n```\nUSAGE\n  $ box hubs:items:manage ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--add <value>...] [--remove <value>...]\n\nARGUMENTS\n  ID  ID of the Box Hub\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --add=<value>...             Add an item to the Box Hub. Format: id=ITEM_ID,type=TYPE,parent-id=PARENT_ID.\n                                   Supported types are file, folder, web_link. The parent-id is the ID of the parent\n                                   block to add the item to. It must be an Item List block. If not provided, the item\n                                   will be added to the first page's first Item List block.\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --remove=<value>...          Remove an item from the Box Hub. Format: id=ITEM_ID,type=TYPE. Supported types are\n                                   file, folder, web_link.\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Add or remove items in a Box Hub\n\nEXAMPLES\n  $ box hubs:items:manage 12345 --add id=11111,type=file,parent-id=67890\n\n  $ box hubs:items:manage 12345 --remove id=22222,type=folder\n```\n\n_See code: [src/commands/hubs/items/manage.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/hubs/items/manage.js)_\n\n## `box hubs:list`\n\nList Box Hubs for the current user\n\n```\nUSAGE\n  $ box hubs:list [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--query <value>]\n    [--scope editable|view_only|all] [--sort name|updated_at|last_accessed_at|view_count|relevance] [--direction\n    ASC|DESC]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --direction=<option>         Sort direction. One of: ASC, DESC\n                                   <options: ASC|DESC>\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --query=<value>              Search query for Box Hubs\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<option>             Scope of hubs to retrieve. One of: editable, view_only, all\n                                   <options: editable|view_only|all>\n      --sort=<option>              Sort field for hubs. One of: name, updated_at, last_accessed_at, view_count,\n                                   relevance\n                                   <options: name|updated_at|last_accessed_at|view_count|relevance>\n\nDESCRIPTION\n  List Box Hubs for the current user\n\nALIASES\n  $ box hubs:list\n\nEXAMPLES\n  $ box hubs\n\n  $ box hubs --query \"Product\" --scope editable --sort name --direction ASC\n```\n\n## `box hubs:update ID`\n\nUpdate a Box Hub\n\n```\nUSAGE\n  $ box hubs:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-T <value>] [-d <value>] [--ai-enabled]\n    [--collaboration-restricted-to-enterprise] [--can-non-owners-invite] [--can-shared-link-be-created]\n    [--can-public-shared-link-be-created]\n\nARGUMENTS\n  ID  ID of the Box Hub to update\n\nFLAGS\n  -T, --title=<value>                                Updated title for the Box Hub\n  -d, --description=<value>                          Updated description for the Box Hub\n  -h, --help                                         Show CLI help\n  -q, --quiet                                        Suppress any non-error output to stderr\n  -s, --save                                         Save report to default reports folder on disk\n  -t, --token=<value>                                Provide a token to perform this call\n  -v, --verbose                                      Show verbose output, which can be helpful for debugging\n  -y, --yes                                          Automatically respond yes to all confirmation prompts\n      --[no-]ai-enabled                              Enable or disable AI features for this Box Hub\n      --as-user=<value>                              Provide an ID for a user\n      --bulk-file-path=<value>                       File path to bulk .csv or .json objects\n      --[no-]can-non-owners-invite                   Allow non-owners to invite collaborators\n      --[no-]can-public-shared-link-be-created       Allow public shared links for this Box Hub\n      --[no-]can-shared-link-be-created              Allow shared links for this Box Hub\n      --[no-]collaboration-restricted-to-enterprise  Restrict collaboration to enterprise users only\n      --csv                                          Output formatted CSV\n      --fields=<value>                               Comma separated list of fields to show\n      --json                                         Output formatted JSON\n      --no-color                                     Turn off colors for logging\n      --save-to-file-path=<value>                    Override default file path to save report\n\nDESCRIPTION\n  Update a Box Hub\n\nEXAMPLES\n  $ box hubs:update 12345 --title \"Updated title\" --ai-enabled\n```\n\n_See code: [src/commands/hubs/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/hubs/update.js)_\n"
  },
  {
    "path": "docs/integration-mappings.md",
    "content": "`box integration-mappings`\n==========================\n\nList Slack integration mappings\n\n* [`box integration-mappings:slack`](#box-integration-mappingsslack)\n* [`box integration-mappings:slack:create BOXITEMID CHANNELID`](#box-integration-mappingsslackcreate-boxitemid-channelid)\n* [`box integration-mappings:slack:delete ID`](#box-integration-mappingsslackdelete-id)\n* [`box integration-mappings:slack:list`](#box-integration-mappingsslacklist)\n* [`box integration-mappings:slack:update ID`](#box-integration-mappingsslackupdate-id)\n* [`box integration-mappings:teams`](#box-integration-mappingsteams)\n* [`box integration-mappings:teams:create BOXITEMID PARTNERITEMID PARTNERITEMTYPE PARTNERITEMTEAMID PARTNERITEMTENANTID`](#box-integration-mappingsteamscreate-boxitemid-partneritemid-partneritemtype-partneritemteamid-partneritemtenantid)\n* [`box integration-mappings:teams:delete ID`](#box-integration-mappingsteamsdelete-id)\n* [`box integration-mappings:teams:list`](#box-integration-mappingsteamslist)\n* [`box integration-mappings:teams:update ID`](#box-integration-mappingsteamsupdate-id)\n\n## `box integration-mappings:slack`\n\nList Slack integration mappings\n\n```\nUSAGE\n  $ box integration-mappings:slack [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--partner-item-id\n    <value>] [--box-item-id <value>] [--manually-created]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --box-item-id=<value>        ID of the mapped Box folder, for which the mapping should be returned\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --[no-]manually-created      Whether the mapping has been manually created\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --partner-item-id=<value>    ID of the mapped Slack channel, for which the mapping should be returned\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List Slack integration mappings\n\nALIASES\n  $ box integration-mappings:slack:list\n\nEXAMPLES\n  $ box integration-mappings:slack --partner-item-id 123 --manually-created\n\n  $ box integration-mappings:slack --box-item-id 456 --no-manually-created\n```\n\n_See code: [src/commands/integration-mappings/slack/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/integration-mappings/slack/index.js)_\n\n## `box integration-mappings:slack:create BOXITEMID CHANNELID`\n\nCreate Slack integration mapping\n\n```\nUSAGE\n  $ box integration-mappings:slack:create BOXITEMID CHANNELID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--slack-workspace-id\n    <value> | --slack-org-id <value>] [--disable-access-management]\n\nARGUMENTS\n  BOXITEMID  ID of the mapped folder\n  CHANNELID  ID of the mapped Slack channel\n\nFLAGS\n  -h, --help                            Show CLI help\n  -q, --quiet                           Suppress any non-error output to stderr\n  -s, --save                            Save report to default reports folder on disk\n  -t, --token=<value>                   Provide a token to perform this call\n  -v, --verbose                         Show verbose output, which can be helpful for debugging\n  -y, --yes                             Automatically respond yes to all confirmation prompts\n      --as-user=<value>                 Provide an ID for a user\n      --bulk-file-path=<value>          File path to bulk .csv or .json objects\n      --csv                             Output formatted CSV\n      --[no-]disable-access-management  Indicates whether or not channel member access to the underlying box item should\n                                        be automatically managed. Depending on type of channel, access is managed\n                                        through creating collaborations or shared links.\n      --fields=<value>                  Comma separated list of fields to show\n      --json                            Output formatted JSON\n      --no-color                        Turn off colors for logging\n      --save-to-file-path=<value>       Override default file path to save report\n      --slack-org-id=<value>            ID of the Slack organization with which the item would be associated\n      --slack-workspace-id=<value>      ID of the Slack workspace with which the item would be associated\n\nDESCRIPTION\n  Create Slack integration mapping\n\nEXAMPLES\n  $ box integration-mappings:slack:create 123 AB89X56Y --slack-org-id 789\n\n  $ box integration-mappings:slack:create 123 AB89X56Y --slack-workspace-id 999 --disable-access-management\n```\n\n_See code: [src/commands/integration-mappings/slack/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/integration-mappings/slack/create.js)_\n\n## `box integration-mappings:slack:delete ID`\n\nDelete Slack integration mapping\n\n```\nUSAGE\n  $ box integration-mappings:slack:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the integration mapping\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete Slack integration mapping\n\nEXAMPLES\n  $ box integration-mappings:slack:delete 123\n```\n\n_See code: [src/commands/integration-mappings/slack/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/integration-mappings/slack/delete.js)_\n\n## `box integration-mappings:slack:list`\n\nList Slack integration mappings\n\n```\nUSAGE\n  $ box integration-mappings:slack:list [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--partner-item-id\n    <value>] [--box-item-id <value>] [--manually-created]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --box-item-id=<value>        ID of the mapped Box folder, for which the mapping should be returned\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --[no-]manually-created      Whether the mapping has been manually created\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --partner-item-id=<value>    ID of the mapped Slack channel, for which the mapping should be returned\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List Slack integration mappings\n\nALIASES\n  $ box integration-mappings:slack:list\n\nEXAMPLES\n  $ box integration-mappings:slack --partner-item-id 123 --manually-created\n\n  $ box integration-mappings:slack --box-item-id 456 --no-manually-created\n```\n\n## `box integration-mappings:slack:update ID`\n\nUpdate Slack integration mapping\n\n```\nUSAGE\n  $ box integration-mappings:slack:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--box-item-id <value>]\n    [--disable-access-management]\n\nARGUMENTS\n  ID  ID of an integration mapping\n\nFLAGS\n  -h, --help                            Show CLI help\n  -q, --quiet                           Suppress any non-error output to stderr\n  -s, --save                            Save report to default reports folder on disk\n  -t, --token=<value>                   Provide a token to perform this call\n  -v, --verbose                         Show verbose output, which can be helpful for debugging\n  -y, --yes                             Automatically respond yes to all confirmation prompts\n      --as-user=<value>                 Provide an ID for a user\n      --box-item-id=<value>             ID of the mapped folder\n      --bulk-file-path=<value>          File path to bulk .csv or .json objects\n      --csv                             Output formatted CSV\n      --[no-]disable-access-management  Indicates whether or not channel member access to the underlying box item should\n                                        be automatically managed. Depending on type of channel, access is managed\n                                        through creating collaborations or shared links.\n      --fields=<value>                  Comma separated list of fields to show\n      --json                            Output formatted JSON\n      --no-color                        Turn off colors for logging\n      --save-to-file-path=<value>       Override default file path to save report\n\nDESCRIPTION\n  Update Slack integration mapping\n\nEXAMPLES\n  $ box integration-mappings:slack:update 123 --box-item-id 789 --disable-access-management\n```\n\n_See code: [src/commands/integration-mappings/slack/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/integration-mappings/slack/update.js)_\n\n## `box integration-mappings:teams`\n\nList Teams integration mappings\n\n```\nUSAGE\n  $ box integration-mappings:teams [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--raw-json | ]\n    [--partner-item-id <value>] [--partner-item-type <value>] [--box-item-id <value>] [--box-item-type <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --box-item-id=<value>        Box item ID, for which the mappings should be returned\n      --box-item-type=<value>      Box item type, for which the mappings should be returned, value is one of: folder\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --partner-item-id=<value>    ID of the mapped item, for which the mapping should be returned\n      --partner-item-type=<value>  Mapped item type, for which the mapping should be returned, value is one of: channel,\n                                   team\n      --raw-json                   Output the raw API JSON response instead of the tsClient-normalized object fields.\n                                   Added as a non-breaking compatibility flag for users who need JSON field names to\n                                   match the API schema exactly. Implies --json.\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List Teams integration mappings\n\nALIASES\n  $ box integration-mappings:teams:list\n\nEXAMPLES\n  $ box integration-mappings:teams --partner-item-id 123 --partner-item-type channel\n\n  $ box integration-mappings:teams --box-item-id 456 --box-item-type folder\n```\n\n_See code: [src/commands/integration-mappings/teams/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/integration-mappings/teams/index.js)_\n\n## `box integration-mappings:teams:create BOXITEMID PARTNERITEMID PARTNERITEMTYPE PARTNERITEMTEAMID PARTNERITEMTENANTID`\n\nCreate Teams integration mapping\n\n```\nUSAGE\n  $ box integration-mappings:teams:create BOXITEMID PARTNERITEMID PARTNERITEMTYPE PARTNERITEMTEAMID PARTNERITEMTENANTID [-t <value>]\n    [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path <value>] [--fields <value>]\n    [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  BOXITEMID            ID of the mapped folder\n  PARTNERITEMID        ID of the mapped item\n  PARTNERITEMTYPE      Type of the mapped item, value is one of: channel, team\n  PARTNERITEMTEAMID    ID of the team that is registered with Microsoft Teams\n  PARTNERITEMTENANTID  ID of the tenant that is registered with Microsoft Teams\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Create Teams integration mapping\n\nEXAMPLES\n  $ box integration-mappings:teams:create 123 19%ABCD-Avgfggkggyftdtfgghjhkhkhh%40thread:tacv2 hjgjgjg-bhhj-564a-b643-hghgj685u abcd-defg-1235-7890\n```\n\n_See code: [src/commands/integration-mappings/teams/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/integration-mappings/teams/create.js)_\n\n## `box integration-mappings:teams:delete ID`\n\nDelete Teams integration mapping\n\n```\nUSAGE\n  $ box integration-mappings:teams:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the integration mapping\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete Teams integration mapping\n\nEXAMPLES\n  $ box integration-mappings:teams:delete 123\n```\n\n_See code: [src/commands/integration-mappings/teams/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/integration-mappings/teams/delete.js)_\n\n## `box integration-mappings:teams:list`\n\nList Teams integration mappings\n\n```\nUSAGE\n  $ box integration-mappings:teams:list [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--raw-json | ]\n    [--partner-item-id <value>] [--partner-item-type <value>] [--box-item-id <value>] [--box-item-type <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --box-item-id=<value>        Box item ID, for which the mappings should be returned\n      --box-item-type=<value>      Box item type, for which the mappings should be returned, value is one of: folder\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --partner-item-id=<value>    ID of the mapped item, for which the mapping should be returned\n      --partner-item-type=<value>  Mapped item type, for which the mapping should be returned, value is one of: channel,\n                                   team\n      --raw-json                   Output the raw API JSON response instead of the tsClient-normalized object fields.\n                                   Added as a non-breaking compatibility flag for users who need JSON field names to\n                                   match the API schema exactly. Implies --json.\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List Teams integration mappings\n\nALIASES\n  $ box integration-mappings:teams:list\n\nEXAMPLES\n  $ box integration-mappings:teams --partner-item-id 123 --partner-item-type channel\n\n  $ box integration-mappings:teams --box-item-id 456 --box-item-type folder\n```\n\n## `box integration-mappings:teams:update ID`\n\nUpdate Teams integration mapping\n\n```\nUSAGE\n  $ box integration-mappings:teams:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--raw-json | ] [--box-item-id <value>]\n\nARGUMENTS\n  ID  ID of an integration mapping\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --box-item-id=<value>        ID of the mapped folder\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --raw-json                   Output the raw API JSON response instead of the tsClient-normalized object fields.\n                                   Added as a non-breaking compatibility flag for users who need JSON field names to\n                                   match the API schema exactly. Implies --json.\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Update Teams integration mapping\n\nEXAMPLES\n  $ box integration-mappings:teams:update 123 --box-item-id 789\n```\n\n_See code: [src/commands/integration-mappings/teams/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/integration-mappings/teams/update.js)_\n"
  },
  {
    "path": "docs/legal-hold-policies.md",
    "content": "`box legal-hold-policies`\n=========================\n\nList legal hold policies\n\n* [`box legal-hold-policies`](#box-legal-hold-policies)\n* [`box legal-hold-policies:assign POLICYID`](#box-legal-hold-policiesassign-policyid)\n* [`box legal-hold-policies:assignments ID`](#box-legal-hold-policiesassignments-id)\n* [`box legal-hold-policies:assignments:delete ID`](#box-legal-hold-policiesassignmentsdelete-id)\n* [`box legal-hold-policies:assignments:get ID`](#box-legal-hold-policiesassignmentsget-id)\n* [`box legal-hold-policies:create POLICYNAME`](#box-legal-hold-policiescreate-policyname)\n* [`box legal-hold-policies:delete ID`](#box-legal-hold-policiesdelete-id)\n* [`box legal-hold-policies:file-version-holds ID`](#box-legal-hold-policiesfile-version-holds-id)\n* [`box legal-hold-policies:file-version-holds:get ID`](#box-legal-hold-policiesfile-version-holdsget-id)\n* [`box legal-hold-policies:get ID`](#box-legal-hold-policiesget-id)\n* [`box legal-hold-policies:update ID`](#box-legal-hold-policiesupdate-id)\n\n## `box legal-hold-policies`\n\nList legal hold policies\n\n```\nUSAGE\n  $ box legal-hold-policies [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--policy-name\n    <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --policy-name=<value>        Filter by policy name\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List legal hold policies\n\nEXAMPLES\n  $ box legal-hold-policies\n```\n\n_See code: [src/commands/legal-hold-policies/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/legal-hold-policies/index.js)_\n\n## `box legal-hold-policies:assign POLICYID`\n\nCreate a new policy assignment\n\n```\nUSAGE\n  $ box legal-hold-policies:assign POLICYID --assign-to-type file_version|file|folder|user --assign-to-id <value> [-t <value>]\n    [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path <value>] [--fields <value>]\n    [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  POLICYID  ID of the legal hold policy to assign\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --assign-to-id=<value>       (required) ID of the object to assign the policy to\n      --assign-to-type=<option>    (required) Type of object to assign the policy to\n                                   <options: file_version|file|folder|user>\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Create a new policy assignment\n\nEXAMPLES\n  $ box legal-hold-policies:assign 99999 --assign-to-type folder --assign-to-id 22222\n```\n\n_See code: [src/commands/legal-hold-policies/assign.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/legal-hold-policies/assign.js)_\n\n## `box legal-hold-policies:assignments ID`\n\nList policy assignments\n\n```\nUSAGE\n  $ box legal-hold-policies:assignments ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--assign-to-type\n    file_version|file|folder|user] [--assign-to-id <value>]\n\nARGUMENTS\n  ID  ID of the legal hold policy get get assignments for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --assign-to-id=<value>       Filter by assignment Id\n      --assign-to-type=<option>    Filter by assignment type\n                                   <options: file_version|file|folder|user>\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List policy assignments\n\nEXAMPLES\n  $ box legal-hold-policies:assignments 99999\n```\n\n_See code: [src/commands/legal-hold-policies/assignments/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/legal-hold-policies/assignments/index.js)_\n\n## `box legal-hold-policies:assignments:delete ID`\n\nDelete a policy assignment\n\n```\nUSAGE\n  $ box legal-hold-policies:assignments:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the policy assignment to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a policy assignment\n\nEXAMPLES\n  $ box legal-hold-policies:assignments:delete 99999\n```\n\n_See code: [src/commands/legal-hold-policies/assignments/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/legal-hold-policies/assignments/delete.js)_\n\n## `box legal-hold-policies:assignments:get ID`\n\nGet information about a policy assignment\n\n```\nUSAGE\n  $ box legal-hold-policies:assignments:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the policy assignment to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a policy assignment\n\nEXAMPLES\n  $ box legal-hold-policies:assignments:get 99999\n```\n\n_See code: [src/commands/legal-hold-policies/assignments/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/legal-hold-policies/assignments/get.js)_\n\n## `box legal-hold-policies:create POLICYNAME`\n\nCreate a new legal hold policy\n\n```\nUSAGE\n  $ box legal-hold-policies:create POLICYNAME [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--description\n    <value>] [--ongoing | [--filter-started-at <value> --filter-ended-at <value>] | ]\n\nARGUMENTS\n  POLICYNAME  Name of the legal hold policy\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --description=<value>        Description of legal hold policy\n      --fields=<value>             Comma separated list of fields to show\n      --filter-ended-at=<value>    Date filter applies to Custodian assignments only. Should be today's date or before.\n                                   Use a RFC3339 timestamp or shorthand syntax 0t, like -5w for 5 weeks ago\n      --filter-started-at=<value>  Date filter applies to Custodian assignments only. Should be today's date or before.\n                                   Use a RFC3339 timestamp or shorthand syntax 0t, like -5w for 5 weeks ago\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --ongoing                    Assignments under this policy will continue applying to files based on events,\n                                   indefinitely\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Create a new legal hold policy\n\nEXAMPLES\n  $ box legal-hold-policies:create \"Class Action Suit\" --ongoing\n```\n\n_See code: [src/commands/legal-hold-policies/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/legal-hold-policies/create.js)_\n\n## `box legal-hold-policies:delete ID`\n\nDelete a legal hold policy\n\n```\nUSAGE\n  $ box legal-hold-policies:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the legal hold policy to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a legal hold policy\n\nEXAMPLES\n  $ box legal-hold-policies:delete 99999\n```\n\n_See code: [src/commands/legal-hold-policies/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/legal-hold-policies/delete.js)_\n\n## `box legal-hold-policies:file-version-holds ID`\n\nList file version legal holds for a legal hold policy\n\n```\nUSAGE\n  $ box legal-hold-policies:file-version-holds ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  ID  ID of the legal hold policy to get holds for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List file version legal holds for a legal hold policy\n\nEXAMPLES\n  $ box legal-hold-policies:file-version-holds 99999\n```\n\n_See code: [src/commands/legal-hold-policies/file-version-holds/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/legal-hold-policies/file-version-holds/index.js)_\n\n## `box legal-hold-policies:file-version-holds:get ID`\n\nGet information about a file version legal hold\n\n```\nUSAGE\n  $ box legal-hold-policies:file-version-holds:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the file version legal hold to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a file version legal hold\n\nEXAMPLES\n  $ box legal-hold-policies:file-version-holds:get 12345\n```\n\n_See code: [src/commands/legal-hold-policies/file-version-holds/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/legal-hold-policies/file-version-holds/get.js)_\n\n## `box legal-hold-policies:get ID`\n\nGet information about a legal hold policy\n\n```\nUSAGE\n  $ box legal-hold-policies:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the legal hold policy to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a legal hold policy\n\nEXAMPLES\n  $ box legal-hold-policies:get 99999\n```\n\n_See code: [src/commands/legal-hold-policies/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/legal-hold-policies/get.js)_\n\n## `box legal-hold-policies:update ID`\n\nUpdate a legal hold policy\n\n```\nUSAGE\n  $ box legal-hold-policies:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--description <value>] [--policy-name\n    <value>] [--release-notes <value>]\n\nARGUMENTS\n  ID  ID of a legal hold policy to update\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --description=<value>        Description of legal hold policy. Max characters 500\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --policy-name=<value>        Name of legal hold policy. Max characters 254\n      --release-notes=<value>      Notes around why the policy was released. Max characters 500\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Update a legal hold policy\n\nEXAMPLES\n  $ box legal-hold-policies:update 99999 --description \"Files related to the ongoing class action suit\"\n```\n\n_See code: [src/commands/legal-hold-policies/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/legal-hold-policies/update.js)_\n"
  },
  {
    "path": "docs/login.md",
    "content": "`box login`\n===========\n\nSign in with OAuth 2.0 and create a new environment (or update an existing one with --reauthorize).\n\nLogin options:\n\n  (1) Official Box CLI App\n      No app setup needed. Use --default-box-app (-d) to skip the prompt.\n\n  (2) Your own Platform OAuth App\n      Enter your Client ID and Client Secret when prompted. Use --platform-app to skip the prompt.\n\nQuickstart: run \"box login -d\" to sign in immediately. A browser window will open for authorization. Once access is granted, the environment is created and set as default — you can start running commands right away.\n\nHeadless environments: use --code (-c) if no browser is available. The CLI will display an authorize URL — visit it in an external browser, authorize and grant access to the app, then provide the state and authorization code back to the CLI when prompted.\n\n* [`box login`](#box-login)\n\n## `box login`\n\nSign in with OAuth 2.0 and create a new environment (or update an existing one with --reauthorize).\n\n```\nUSAGE\n  $ box login [--no-color] [-h] [-v] [-q] [-c] [-p <value>] [-d | --platform-app] [-r -n <value>] [-i]\n\nFLAGS\n  -c, --code\n      Manually provide state and authorization code instead of using a local callback server. Use this in headless\n      environments where no browser is available — the CLI will display an authorize URL to visit externally.\n\n  -d, --default-box-app\n      Use the Official Box CLI app flow and proceed directly to authorization.\n      This is the fastest way to integrate with Box — no app creation in the Developer Console is needed.\n      Scopes are limited to content actions, allowing you to effectively operate with your files and folders.\n      This flow requires a local callback server on a supported port (3000, 3001, 4000, 5000, or 8080). The default port\n      is 3000; use --port to change it.\n\n  -h, --help\n      Show CLI help\n\n  -i, --incognito-browser\n      Visit authorize URL with incognito browser\n\n  -n, --name=<value>\n      [default: oauth] Set a name for the environment\n\n  -p, --port=<value>\n      [default: 3000] Set the port number for the local OAuth callback server\n\n  -q, --quiet\n      Suppress any non-error output to stderr\n\n  -r, --reauthorize\n      Reauthorize the existing environment with given `name`\n\n  -v, --verbose\n      Show verbose output, which can be helpful for debugging\n\n  --no-color\n      Turn off colors for logging\n\n  --platform-app\n      Skip the authentication method prompt and go directly to Platform App setup.\n      You will be prompted for Client ID and Client Secret.\n\nDESCRIPTION\n  Sign in with OAuth 2.0 and create a new environment (or update an existing one with --reauthorize).\n\n  Login options:\n\n  (1) Official Box CLI App\n  No app setup needed. Use --default-box-app (-d) to skip the prompt.\n\n  (2) Your own Platform OAuth App\n  Enter your Client ID and Client Secret when prompted. Use --platform-app to skip the prompt.\n\n  Quickstart: run \"box login -d\" to sign in immediately. A browser window will open for authorization. Once access is\n  granted, the environment is created and set as default — you can start running commands right away.\n\n  Headless environments: use --code (-c) if no browser is available. The CLI will display an authorize URL — visit it in\n  an external browser, authorize and grant access to the app, then provide the state and authorization code back to the\n  CLI when prompted.\n```\n\n_See code: [src/commands/login.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/login.js)_\n"
  },
  {
    "path": "docs/logout.md",
    "content": "`box logout`\n============\n\nRevoke the access token and clear local token cache.\n\nFor OAuth, run `box login` to authorize again.\nFor CCG and JWT, a new token is fetched automatically on the next command.\n\nUse -f and --on-revoke-failure=clear or --on-revoke-failure=abort to skip the interactive prompt.\n\n* [`box logout`](#box-logout)\n\n## `box logout`\n\nRevoke the access token and clear local token cache.\n\n```\nUSAGE\n  $ box logout [--no-color] [-h] [-v] [-q] [-f] [--on-revoke-failure clear|abort]\n\nFLAGS\n  -f, --force                       Skip confirmation prompt\n  -h, --help                        Show CLI help\n  -q, --quiet                       Suppress any non-error output to stderr\n  -v, --verbose                     Show verbose output, which can be helpful for debugging\n      --no-color                    Turn off colors for logging\n      --on-revoke-failure=<option>  On revoke failure: \"clear\" clears local cache only, \"abort\" exits without clearing.\n                                    Skips prompt.\n                                    <options: clear|abort>\n\nDESCRIPTION\n  Revoke the access token and clear local token cache.\n\n  For OAuth, run `box login` to authorize again.\n  For CCG and JWT, a new token is fetched automatically on the next command.\n\n  Use -f and --on-revoke-failure=clear or --on-revoke-failure=abort to skip the interactive prompt.\n```\n\n_See code: [src/commands/logout.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/logout.js)_\n"
  },
  {
    "path": "docs/metadata-cascade-policies.md",
    "content": "`box metadata-cascade-policies`\n===============================\n\nList the metadata cascade policies on a folder\n\n* [`box metadata-cascade-policies FOLDERID`](#box-metadata-cascade-policies-folderid)\n* [`box metadata-cascade-policies:create TEMPLATEKEY`](#box-metadata-cascade-policiescreate-templatekey)\n* [`box metadata-cascade-policies:delete ID`](#box-metadata-cascade-policiesdelete-id)\n* [`box metadata-cascade-policies:force-apply ID`](#box-metadata-cascade-policiesforce-apply-id)\n* [`box metadata-cascade-policies:get ID`](#box-metadata-cascade-policiesget-id)\n\n## `box metadata-cascade-policies FOLDERID`\n\nList the metadata cascade policies on a folder\n\n```\nUSAGE\n  $ box metadata-cascade-policies FOLDERID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n    [--owner-enterprise-id <value>]\n\nARGUMENTS\n  FOLDERID  The ID of the folder to list cascade policies for\n\nFLAGS\n  -h, --help                         Show CLI help\n  -q, --quiet                        Suppress any non-error output to stderr\n  -s, --save                         Save report to default reports folder on disk\n  -t, --token=<value>                Provide a token to perform this call\n  -v, --verbose                      Show verbose output, which can be helpful for debugging\n  -y, --yes                          Automatically respond yes to all confirmation prompts\n      --as-user=<value>              Provide an ID for a user\n      --bulk-file-path=<value>       File path to bulk .csv or .json objects\n      --csv                          Output formatted CSV\n      --fields=<value>               Comma separated list of fields to show\n      --json                         Output formatted JSON\n      --max-items=<value>            A value that indicates the maximum number of results to return. This only specifies\n                                     a maximum boundary and will not guarantee the minimum number of results returned.\n                                     When the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests\n                                     will be made.\n      --no-color                     Turn off colors for logging\n      --owner-enterprise-id=<value>  The ID of the enterprise to filter cascade policies for\n      --save-to-file-path=<value>    Override default file path to save report\n\nDESCRIPTION\n  List the metadata cascade policies on a folder\n\nEXAMPLES\n  $ box metadata-cascade-policies 22222\n```\n\n_See code: [src/commands/metadata-cascade-policies/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/metadata-cascade-policies/index.js)_\n\n## `box metadata-cascade-policies:create TEMPLATEKEY`\n\nCreate a new metadata cascade policy on a folder\n\n```\nUSAGE\n  $ box metadata-cascade-policies:create TEMPLATEKEY --folder <value> [-t <value>] [--as-user <value>] [--no-color] [--json | --csv]\n    [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--id-only]\n    [--scope <value>]\n\nARGUMENTS\n  TEMPLATEKEY  The template key of the metadata template to cascade\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --folder=<value>             (required) The ID of the folder to cascade metadata on\n      --id-only                    Return only an ID to output from this command\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to cascade\n\nDESCRIPTION\n  Create a new metadata cascade policy on a folder\n\nALIASES\n  $ box metadata-cascade-policies:create\n\nEXAMPLES\n  $ box metadata-templates:cascade employeeRecord --folder 22222\n```\n\n## `box metadata-cascade-policies:delete ID`\n\nDelete a metadata cascade policy\n\n```\nUSAGE\n  $ box metadata-cascade-policies:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  The ID of the metadata cascade policy to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a metadata cascade policy\n\nEXAMPLES\n  $ box metadata-cascade-policies:delete 12345\n```\n\n_See code: [src/commands/metadata-cascade-policies/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/metadata-cascade-policies/delete.js)_\n\n## `box metadata-cascade-policies:force-apply ID`\n\nForce apply a cascade policy to the existing items in a folder\n\n```\nUSAGE\n  $ box metadata-cascade-policies:force-apply ID --conflict-resolution none|overwrite [-t <value>] [--as-user <value>] [--no-color] [--json\n    | --csv] [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  The ID of the cascade policy to force apply\n\nFLAGS\n  -h, --help                          Show CLI help\n  -q, --quiet                         Suppress any non-error output to stderr\n  -s, --save                          Save report to default reports folder on disk\n  -t, --token=<value>                 Provide a token to perform this call\n  -v, --verbose                       Show verbose output, which can be helpful for debugging\n  -y, --yes                           Automatically respond yes to all confirmation prompts\n      --as-user=<value>               Provide an ID for a user\n      --bulk-file-path=<value>        File path to bulk .csv or .json objects\n      --conflict-resolution=<option>  (required) The way to resolve conflicts with the metadata being applied\n                                      <options: none|overwrite>\n      --csv                           Output formatted CSV\n      --fields=<value>                Comma separated list of fields to show\n      --json                          Output formatted JSON\n      --no-color                      Turn off colors for logging\n      --save-to-file-path=<value>     Override default file path to save report\n\nDESCRIPTION\n  Force apply a cascade policy to the existing items in a folder\n\nEXAMPLES\n  $ box metadata-cascade-policies:force-apply 12345 --conflict-resolution overwrite\n```\n\n_See code: [src/commands/metadata-cascade-policies/force-apply.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/metadata-cascade-policies/force-apply.js)_\n\n## `box metadata-cascade-policies:get ID`\n\nGet information about a metadata cascade policy\n\n```\nUSAGE\n  $ box metadata-cascade-policies:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  The ID of the cascade policy to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a metadata cascade policy\n\nEXAMPLES\n  $ box metadata-cascade-policies:get 12345\n```\n\n_See code: [src/commands/metadata-cascade-policies/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/metadata-cascade-policies/get.js)_\n"
  },
  {
    "path": "docs/metadata-query.md",
    "content": "`box metadata-query`\n====================\n\nCreate a search using SQL-like syntax to return items that match specific metadata\n\n* [`box metadata-query FROM ANCESTORFOLDERID`](#box-metadata-query-from-ancestorfolderid)\n\n## `box metadata-query FROM ANCESTORFOLDERID`\n\nCreate a search using SQL-like syntax to return items that match specific metadata\n\n```\nUSAGE\n  $ box metadata-query FROM ANCESTORFOLDERID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--query-params\n    <value> --query <value>] [--query-param <value>... ] [--query-param-array <value>... ] [--use-index <value>]\n    [--order-by <value>] [--limit <value>] [--marker <value>] [--extra-fields <value>]\n\nARGUMENTS\n  FROM              The template used in the query. Must be in the form scope.templateKey (for example\n                    enterprise_12345.contractTemplate)\n  ANCESTORFOLDERID  The folder_id to which to restrain the query\n\nFLAGS\n  -h, --help                          Show CLI help\n  -q, --quiet                         Suppress any non-error output to stderr\n  -s, --save                          Save report to default reports folder on disk\n  -t, --token=<value>                 Provide a token to perform this call\n  -v, --verbose                       Show verbose output, which can be helpful for debugging\n  -y, --yes                           Automatically respond yes to all confirmation prompts\n      --as-user=<value>               Provide an ID for a user\n      --bulk-file-path=<value>        File path to bulk .csv or .json objects\n      --csv                           Output formatted CSV\n      --extra-fields=<value>          A list of additional attributes to return for any item, including its metadata.\n      --fields=<value>                Comma separated list of fields to show\n      --json                          Output formatted JSON\n      --limit=<value>                 A value between 0 and 100 that indicates the maximum number of results to return\n                                      for a single request. This only specifies a maximum boundary and will not\n                                      guarantee the minimum number of results returned.\n      --marker=<value>                Marker to use for requesting the next page.\n      --no-color                      Turn off colors for logging\n      --order-by=<value>              A list of template fields and directions to sort the metadata query results by.\n      --query=<value>                 The logical expression of the query\n      --query-param=<value>...        One query param key-value pair, i.e. key=value. If this key duplicates with\n                                      query-params, this flag will take precedence.\n      --query-param-array=<value>...  One query param key-multiple-value pair, use for multiple-values fields, i.e.\n                                      key=value1,value2,value3. If this key duplicates with query-params or query-param,\n                                      this flag will take precedence.\n      --query-params=<value>          The arguments for the query. Can be specified as a comma-separated list of\n                                      key-value pairs. i.e. key1=value1,key2=value2\n      --save-to-file-path=<value>     Override default file path to save report\n      --use-index=<value>             The name of the search index to use for this query.\n\nDESCRIPTION\n  Create a search using SQL-like syntax to return items that match specific metadata\n\nEXAMPLES\n  $ box metadata-query enterprise_12345.someTemplate 5555 --query \"amount >= :minAmount AND amount <= :maxAmount\" --query-params minAmount=100f,maxAmount=200f --use-index amountAsc --order-by amount=ASC --extra-fields created_at,metadata.enterprise_1234.contracts\n\n  $ box metadata-query enterprise_12345.contractTemplate 12345 --query \"status = :status\" --query-param status=active\n```\n\n_See code: [src/commands/metadata-query.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/metadata-query.js)_\n"
  },
  {
    "path": "docs/metadata-templates.md",
    "content": "`box metadata-templates`\n========================\n\nGet all metadata templates in your Enterprise\n\n* [`box metadata-templates`](#box-metadata-templates)\n* [`box metadata-templates:cascade TEMPLATEKEY`](#box-metadata-templatescascade-templatekey)\n* [`box metadata-templates:create`](#box-metadata-templatescreate)\n* [`box metadata-templates:delete TEMPLATEKEY`](#box-metadata-templatesdelete-templatekey)\n* [`box metadata-templates:get TEMPLATEKEY`](#box-metadata-templatesget-templatekey)\n* [`box metadata-templates:list`](#box-metadata-templateslist)\n* [`box metadata-templates:update TEMPLATEKEY`](#box-metadata-templatesupdate-templatekey)\n\n## `box metadata-templates`\n\nGet all metadata templates in your Enterprise\n\n```\nUSAGE\n  $ box metadata-templates [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get all metadata templates in your Enterprise\n\nALIASES\n  $ box metadata-templates:list\n\nEXAMPLES\n  $ box metadata-templates:list\n\n  $ box metadata-templates:list --json\n\n  $ box metadata-templates:list --fields templateKey,displayName,scope\n```\n\n_See code: [src/commands/metadata-templates/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/metadata-templates/index.js)_\n\n## `box metadata-templates:cascade TEMPLATEKEY`\n\nCreate a new metadata cascade policy on a folder\n\n```\nUSAGE\n  $ box metadata-templates:cascade TEMPLATEKEY --folder <value> [-t <value>] [--as-user <value>] [--no-color] [--json | --csv]\n    [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--id-only]\n    [--scope <value>]\n\nARGUMENTS\n  TEMPLATEKEY  The template key of the metadata template to cascade\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --folder=<value>             (required) The ID of the folder to cascade metadata on\n      --id-only                    Return only an ID to output from this command\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to cascade\n\nDESCRIPTION\n  Create a new metadata cascade policy on a folder\n\nALIASES\n  $ box metadata-cascade-policies:create\n\nEXAMPLES\n  $ box metadata-templates:cascade employeeRecord --folder 22222\n```\n\n_See code: [src/commands/metadata-templates/cascade.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/metadata-templates/cascade.js)_\n\n## `box metadata-templates:create`\n\nCreate a new metadata template\n\n```\nUSAGE\n  $ box metadata-templates:create --display-name <value> [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--scope <value>]\n    [--template-key <value>] [--hidden] [--string <value>...] [--enum <value>...] [--date <value>...] [--number\n    <value>...] [--multi-select <value>...] [--field-key <value>...] [--description <value>...] [--option <value>...]\n    [--id-only] [--copy-instance-on-item-copy]\n\nFLAGS\n  -h, --help                        Show CLI help\n  -q, --quiet                       Suppress any non-error output to stderr\n  -s, --save                        Save report to default reports folder on disk\n  -t, --token=<value>               Provide a token to perform this call\n  -v, --verbose                     Show verbose output, which can be helpful for debugging\n  -y, --yes                         Automatically respond yes to all confirmation prompts\n      --as-user=<value>             Provide an ID for a user\n      --bulk-file-path=<value>      File path to bulk .csv or .json objects\n      --copy-instance-on-item-copy  Whether to include the metadata when a file or folder is copied\n      --csv                         Output formatted CSV\n      --date=<value>...             Add a date field with the provided display name\n      --description=<value>...      Set the description of a field\n      --display-name=<value>        (required) The display name of the metadata template\n      --enum=<value>...             Add an enum field with the provided display name\n      --field-key=<value>...        Set the key of a field\n      --fields=<value>              Comma separated list of fields to show\n      --[no-]hidden                 Whether this template or field is hidden in the UI\n      --id-only                     Return only an ID to output from this command\n      --json                        Output formatted JSON\n      --multi-select=<value>...     Add a multi-select field with the provided display name\n      --no-color                    Turn off colors for logging\n      --number=<value>...           Add a numeric field with the provided display name\n      --option=<value>...           Add an option to a field\n      --save-to-file-path=<value>   Override default file path to save report\n      --scope=<value>               [default: enterprise] The scope of the metadata template\n      --string=<value>...           Add a string field with the provided name\n      --template-key=<value>        A unique identifier for the template.  If not specified, will be derived from the\n                                    display name\n\nDESCRIPTION\n  Create a new metadata template\n\nEXAMPLES\n  $ box metadata-templates:create --display-name \"Employee Record\" --string Name --enum Department --option Sales\n```\n\n_See code: [src/commands/metadata-templates/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/metadata-templates/create.js)_\n\n## `box metadata-templates:delete TEMPLATEKEY`\n\nDelete a metadata template\n\n```\nUSAGE\n  $ box metadata-templates:delete TEMPLATEKEY [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--scope <value>]\n\nARGUMENTS\n  TEMPLATEKEY  The template key of the metadata template to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to delete\n\nDESCRIPTION\n  Delete a metadata template\n\nEXAMPLES\n  $ box metadata-templates:delete employeeRecord\n```\n\n_See code: [src/commands/metadata-templates/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/metadata-templates/delete.js)_\n\n## `box metadata-templates:get TEMPLATEKEY`\n\nGet information about a metadata template\n\n```\nUSAGE\n  $ box metadata-templates:get TEMPLATEKEY [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--scope <value>]\n\nARGUMENTS\n  TEMPLATEKEY  The template key of the template to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --scope=<value>              [default: enterprise] The scope of the metadata template to get\n\nDESCRIPTION\n  Get information about a metadata template\n\nEXAMPLES\n  $ box metadata-templates:get employeeRecord\n```\n\n_See code: [src/commands/metadata-templates/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/metadata-templates/get.js)_\n\n## `box metadata-templates:list`\n\nGet all metadata templates in your Enterprise\n\n```\nUSAGE\n  $ box metadata-templates:list [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get all metadata templates in your Enterprise\n\nALIASES\n  $ box metadata-templates:list\n\nEXAMPLES\n  $ box metadata-templates:list\n\n  $ box metadata-templates:list --json\n\n  $ box metadata-templates:list --fields templateKey,displayName,scope\n```\n\n## `box metadata-templates:update TEMPLATEKEY`\n\nUpdate a metadata template\n\n```\nUSAGE\n  $ box metadata-templates:update TEMPLATEKEY [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--display-name\n    <value>...] [--scope <value>] [--hidden] [--string <value>...] [--enum <value>...] [--date <value>...] [--number\n    <value>...] [--multi-select <value>...] [--add-multi-select-option <value>...] [--field-key <value>...]\n    [--description <value>...] [--option <value>...] [--add-enum-option <value>...] [--reorder-enum-options <value>...]\n    [--reorder-fields <value>] [--edit-field <value>] [--edit-enum-option <value>] [--remove-enum-option <value>]\n    [--remove-field <value>] [--copy-instance-on-item-copy]\n\nARGUMENTS\n  TEMPLATEKEY  The key of the template to update\n\nFLAGS\n  -h, --help                                Show CLI help\n  -q, --quiet                               Suppress any non-error output to stderr\n  -s, --save                                Save report to default reports folder on disk\n  -t, --token=<value>                       Provide a token to perform this call\n  -v, --verbose                             Show verbose output, which can be helpful for debugging\n  -y, --yes                                 Automatically respond yes to all confirmation prompts\n      --add-enum-option=<value>...          Add an enum option to the specified field; must be followed by one or more\n                                            --option flags\n      --add-multi-select-option=<value>...  Add an option to a specified multiselect field; must be followed by one or\n                                            more --option flags\n      --as-user=<value>                     Provide an ID for a user\n      --bulk-file-path=<value>              File path to bulk .csv or .json objects\n      --[no-]copy-instance-on-item-copy     Whether to include the metadata when a file or folder is copied\n      --csv                                 Output formatted CSV\n      --date=<value>...                     Add a date field with the provided display name\n      --description=<value>...              Set the description of a field\n      --display-name=<value>...             The display name of the metadata template or field\n      --edit-enum-option=<value>            Edit the specified enum option; must be followed by an --option flag\n      --edit-field=<value>                  Edit the specified field; must be followed by flags to apply to the field\n      --enum=<value>...                     Add an enum field with the provided display name\n      --field-key=<value>...                Set the key of a field\n      --fields=<value>                      Comma separated list of fields to show\n      --[no-]hidden                         Whether this template or field is hidden in the UI\n      --json                                Output formatted JSON\n      --multi-select=<value>...             Add a multi-select field with the provided display name\n      --no-color                            Turn off colors for logging\n      --number=<value>...                   Add a numeric field with the provided display name\n      --option=<value>...                   Specify a field option\n      --remove-enum-option=<value>          Removes the specified enum field option; must be in the form\n                                            fieldKey.optionKey\n      --remove-field=<value>                Remove the specified field\n      --reorder-enum-options=<value>...     Reorder the options for a given field; must be followed by one or more\n                                            --option flags\n      --reorder-fields=<value>              Reorder the template fields; must be in the form first_key,second_key,...\n      --save-to-file-path=<value>           Override default file path to save report\n      --scope=<value>                       [default: enterprise] The scope of the metadata template\n      --string=<value>...                   Add a string field with the provided name\n\nDESCRIPTION\n  Update a metadata template\n\nEXAMPLES\n  $ box metadata-templates:update employeeRecord --hidden\n```\n\n_See code: [src/commands/metadata-templates/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/metadata-templates/update.js)_\n"
  },
  {
    "path": "docs/oss.md",
    "content": "`box oss`\n=========\n\nPrint a list of open-source licensed packages used in the Box CLI\n\n* [`box oss`](#box-oss)\n\n## `box oss`\n\nPrint a list of open-source licensed packages used in the Box CLI\n\n```\nUSAGE\n  $ box oss [--no-color] [-h] [-v] [-q]\n\nFLAGS\n  -h, --help      Show CLI help\n  -q, --quiet     Suppress any non-error output to stderr\n  -v, --verbose   Show verbose output, which can be helpful for debugging\n      --no-color  Turn off colors for logging\n\nDESCRIPTION\n  Print a list of open-source licensed packages used in the Box CLI\n```\n\n_See code: [src/commands/oss.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/oss.js)_\n"
  },
  {
    "path": "docs/recent-items.md",
    "content": "`box recent-items`\n==================\n\nList information about files accessed in the past 90 days up to a 1000 items\n\n* [`box recent-items`](#box-recent-items)\n\n## `box recent-items`\n\nList information about files accessed in the past 90 days up to a 1000 items\n\n```\nUSAGE\n  $ box recent-items [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List information about files accessed in the past 90 days up to a 1000 items\n\nEXAMPLES\n  $ box recent-items\n```\n\n_See code: [src/commands/recent-items.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/recent-items.js)_\n"
  },
  {
    "path": "docs/request.md",
    "content": "`box request`\n=============\n\nManually specify a Box API request\n\n* [`box request RESOURCE`](#box-request-resource)\n\n## `box request RESOURCE`\n\nManually specify a Box API request\n\n```\nUSAGE\n  $ box request RESOURCE [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-X\n    GET|POST|PUT|DELETE|OPTIONS] [--query <value>] [--body <value>] [-H <value>...]\n\nARGUMENTS\n  RESOURCE  The Box API resource to make a request against, e.g. /search or https://api.box.com/2.0/search\n\nFLAGS\n  -H, --header=<value>...          HTTP header to add to the request, e.g. \"Header: value\"\n  -X, --method=<option>            [default: GET] The HTTP method for the request\n                                   <options: GET|POST|PUT|DELETE|OPTIONS>\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --body=<value>               Body of the request\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --query=<value>              Query params to use for the request, either as k1=v1&k2=v2 or as JSON\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Manually specify a Box API request\n\nEXAMPLES\n  $ box request /users/me\n\n  $ box request /folders/0/items --query \"limit=5\"\n\n  $ box request /folders -X POST --body '{\"name\":\"New Folder\",\"parent\":{\"id\":\"0\"}}'\n```\n\n_See code: [src/commands/request.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/request.js)_\n"
  },
  {
    "path": "docs/retention-policies.md",
    "content": "`box retention-policies`\n========================\n\nList all retention policies for your enterprise\n\n* [`box retention-policies`](#box-retention-policies)\n* [`box retention-policies:assign POLICYID`](#box-retention-policiesassign-policyid)\n* [`box retention-policies:assignments ID`](#box-retention-policiesassignments-id)\n* [`box retention-policies:assignments:get ID`](#box-retention-policiesassignmentsget-id)\n* [`box retention-policies:assignments:remove ID`](#box-retention-policiesassignmentsremove-id)\n* [`box retention-policies:create POLICYNAME`](#box-retention-policiescreate-policyname)\n* [`box retention-policies:file-version-retentions`](#box-retention-policiesfile-version-retentions)\n* [`box retention-policies:file-version-retentions:get ID`](#box-retention-policiesfile-version-retentionsget-id)\n* [`box retention-policies:file-versions-under-retention:get ID`](#box-retention-policiesfile-versions-under-retentionget-id)\n* [`box retention-policies:files-under-retention:get ID`](#box-retention-policiesfiles-under-retentionget-id)\n* [`box retention-policies:get ID`](#box-retention-policiesget-id)\n* [`box retention-policies:update ID`](#box-retention-policiesupdate-id)\n\n## `box retention-policies`\n\nList all retention policies for your enterprise\n\n```\nUSAGE\n  $ box retention-policies [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [-n <value>]\n    [--policy-type finite|indefinite] [-u <value>]\n\nFLAGS\n  -h, --help                        Show CLI help\n  -n, --policy-name=<value>         A name to filter the retention policies by\n  -q, --quiet                       Suppress any non-error output to stderr\n  -s, --save                        Save report to default reports folder on disk\n  -t, --token=<value>               Provide a token to perform this call\n  -u, --created-by-user-id=<value>  A user id to filter the retention policies by\n  -v, --verbose                     Show verbose output, which can be helpful for debugging\n  -y, --yes                         Automatically respond yes to all confirmation prompts\n      --as-user=<value>             Provide an ID for a user\n      --bulk-file-path=<value>      File path to bulk .csv or .json objects\n      --csv                         Output formatted CSV\n      --fields=<value>              Comma separated list of fields to show\n      --json                        Output formatted JSON\n      --max-items=<value>           A value that indicates the maximum number of results to return. This only specifies\n                                    a maximum boundary and will not guarantee the minimum number of results returned.\n                                    When the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests\n                                    will be made.\n      --no-color                    Turn off colors for logging\n      --policy-type=<option>        A policy type to filter the retention policies by\n                                    <options: finite|indefinite>\n      --save-to-file-path=<value>   Override default file path to save report\n\nDESCRIPTION\n  List all retention policies for your enterprise\n\nEXAMPLES\n  $ box retention-policies\n```\n\n_See code: [src/commands/retention-policies/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/retention-policies/index.js)_\n\n## `box retention-policies:assign POLICYID`\n\nAssign a retention policy assignment\n\n```\nUSAGE\n  $ box retention-policies:assign POLICYID --assign-to-type enterprise|folder|metadata_template [-t <value>] [--as-user\n    <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path\n    <value>] [-h] [-v] [-y] [-q] [--assign-to-id <value>] [--filter-field <value>...] [--start-date-field <value>]\n\nARGUMENTS\n  POLICYID  The ID of the retention policy to assign this content to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --assign-to-id=<value>       The ID of the content to assign the retention policy to\n      --assign-to-type=<option>    (required) The type of the content to assign the retention policy to\n                                   <options: enterprise|folder|metadata_template>\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --filter-field=<value>...    Metadata fields to filter against, if assigning to a metadata template.Allow\n                                   properties: field, value. Example: --filter-field=fieldName=fieldValue\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --start-date-field=<value>   The date the retention policy assignment begins\n\nDESCRIPTION\n  Assign a retention policy assignment\n\nEXAMPLES\n  $ box retention-policies:assign 12345 --assign-to-type folder --assign-to-id 22222 --filter-field=fieldName=fieldValue --start-date-field=upload_date\n```\n\n_See code: [src/commands/retention-policies/assign.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/retention-policies/assign.js)_\n\n## `box retention-policies:assignments ID`\n\nList all retention policies for your enterprise\n\n```\nUSAGE\n  $ box retention-policies:assignments ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [--type\n    folder|enterprise|metadata_template]\n\nARGUMENTS\n  ID  ID of the retention policy to get assignments for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --type=<option>              The type of the retention policy assignment to retrieve\n                                   <options: folder|enterprise|metadata_template>\n\nDESCRIPTION\n  List all retention policies for your enterprise\n\nEXAMPLES\n  $ box retention-policies:assignments 12345\n```\n\n_See code: [src/commands/retention-policies/assignments/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/retention-policies/assignments/index.js)_\n\n## `box retention-policies:assignments:get ID`\n\nGet information about a retention policy assignment\n\n```\nUSAGE\n  $ box retention-policies:assignments:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the retention policy assignment to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a retention policy assignment\n\nEXAMPLES\n  $ box retention-policies:assignments:get 1235\n```\n\n_See code: [src/commands/retention-policies/assignments/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/retention-policies/assignments/get.js)_\n\n## `box retention-policies:assignments:remove ID`\n\nRemove a retention policy assignment applied to content\n\n```\nUSAGE\n  $ box retention-policies:assignments:remove ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the retention policy assignment to remove\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Remove a retention policy assignment applied to content\n\nEXAMPLES\n  $ box retention-policies:assignments:remove 1235\n```\n\n_See code: [src/commands/retention-policies/assignments/remove.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/retention-policies/assignments/remove.js)_\n\n## `box retention-policies:create POLICYNAME`\n\nCreate a new retention policy\n\n```\nUSAGE\n  $ box retention-policies:create POLICYNAME --disposition-action permanently_delete|remove_retention [-t <value>] [--as-user\n    <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path\n    <value>] [-h] [-v] [-y] [-q] [--notify-owners] [--allow-extension] [-l <value>] [--retention-type\n    modifiable|non_modifiable |  | ] [--description <value>] [--custom-notification-recipient <value>...]\n\nARGUMENTS\n  POLICYNAME  Name of retention policy to be created\n\nFLAGS\n  -h, --help                                      Show CLI help\n  -l, --retention-length=<value>                  The number of days to apply the retention policy. If not set, policy\n                                                  will be indefinite\n  -q, --quiet                                     Suppress any non-error output to stderr\n  -s, --save                                      Save report to default reports folder on disk\n  -t, --token=<value>                             Provide a token to perform this call\n  -v, --verbose                                   Show verbose output, which can be helpful for debugging\n  -y, --yes                                       Automatically respond yes to all confirmation prompts\n      --[no-]allow-extension                      The owner of a file will be allowed to extend the retention\n      --as-user=<value>                           Provide an ID for a user\n      --bulk-file-path=<value>                    File path to bulk .csv or .json objects\n      --csv                                       Output formatted CSV\n      --custom-notification-recipient=<value>...  A list of users notified when the retention policy duration is about\n                                                  to end. Allowed properties are: id, type, login, name\n      --description=<value>                       The additional text description of the retention policy\n      --disposition-action=<option>               (required) For indefinite policies, disposition action must be\n                                                  remove_retention\n                                                  <options: permanently_delete|remove_retention>\n      --fields=<value>                            Comma separated list of fields to show\n      --json                                      Output formatted JSON\n      --no-color                                  Turn off colors for logging\n      --[no-]notify-owners                        The owner or co-owner will get notified when a file is nearing\n                                                  expiration\n      --retention-type=<option>                   The type of retention for the new policy\n                                                  <options: modifiable|non_modifiable>\n      --save-to-file-path=<value>                 Override default file path to save report\n\nDESCRIPTION\n  Create a new retention policy\n\nEXAMPLES\n  $ box retention-policies:create \"Tax Documents\" --retention-length 2555 --disposition-action=remove_retention --notify-owners --allow-extension --description \"Tax documents for 2018\" --custom-notification-recipient=id=12345,login=user@box.com\n```\n\n_See code: [src/commands/retention-policies/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/retention-policies/create.js)_\n\n## `box retention-policies:file-version-retentions`\n\nList all file version retentions for your enterprise\n\n```\nUSAGE\n  $ box retention-policies:file-version-retentions [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n    [--disposition-action permanently_delete|remove_retention] [--disposition-after <value>] [--disposition-before\n    <value>] [--file-id <value>] [--file-version-id <value>] [--policy-id <value>]\n\nFLAGS\n  -h, --help                         Show CLI help\n  -q, --quiet                        Suppress any non-error output to stderr\n  -s, --save                         Save report to default reports folder on disk\n  -t, --token=<value>                Provide a token to perform this call\n  -v, --verbose                      Show verbose output, which can be helpful for debugging\n  -y, --yes                          Automatically respond yes to all confirmation prompts\n      --as-user=<value>              Provide an ID for a user\n      --bulk-file-path=<value>       File path to bulk .csv or .json objects\n      --csv                          Output formatted CSV\n      --disposition-action=<option>  A disposition action to filter by\n                                     <options: permanently_delete|remove_retention>\n      --disposition-after=<value>    A date to filter retention policies that complete after a certain time\n      --disposition-before=<value>   A date to filter retention policies that complete before a certain time\n      --fields=<value>               Comma separated list of fields to show\n      --file-id=<value>              A file id to filter the file version retentions by\n      --file-version-id=<value>      A file version id to filter the file version retentions by\n      --json                         Output formatted JSON\n      --max-items=<value>            A value that indicates the maximum number of results to return. This only specifies\n                                     a maximum boundary and will not guarantee the minimum number of results returned.\n                                     When the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests\n                                     will be made.\n      --no-color                     Turn off colors for logging\n      --policy-id=<value>            A policy id to filter the file version retentions by\n      --save-to-file-path=<value>    Override default file path to save report\n\nDESCRIPTION\n  List all file version retentions for your enterprise\n\nEXAMPLES\n  $ box retention-policies:file-version-retentions\n```\n\n_See code: [src/commands/retention-policies/file-version-retentions/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/retention-policies/file-version-retentions/index.js)_\n\n## `box retention-policies:file-version-retentions:get ID`\n\nGet information about a file version retention policy\n\n```\nUSAGE\n  $ box retention-policies:file-version-retentions:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the file version retention to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a file version retention policy\n\nEXAMPLES\n  $ box retention-policies:file-version-retentions:get 77777\n```\n\n_See code: [src/commands/retention-policies/file-version-retentions/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/retention-policies/file-version-retentions/get.js)_\n\n## `box retention-policies:file-versions-under-retention:get ID`\n\nGet information about file versions under retention for assignment\n\n```\nUSAGE\n  $ box retention-policies:file-versions-under-retention:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  ID  ID of the retention policy assignment\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about file versions under retention for assignment\n\nEXAMPLES\n  $ box retention-policies:file-versions-under-retention:get 77777\n```\n\n_See code: [src/commands/retention-policies/file-versions-under-retention/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/retention-policies/file-versions-under-retention/get.js)_\n\n## `box retention-policies:files-under-retention:get ID`\n\nGet information about files under retention for assignment\n\n```\nUSAGE\n  $ box retention-policies:files-under-retention:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  ID  ID of the retention policy assignment\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about files under retention for assignment\n\nEXAMPLES\n  $ box retention-policies:files-under-retention:get 77777\n```\n\n_See code: [src/commands/retention-policies/files-under-retention/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/retention-policies/files-under-retention/get.js)_\n\n## `box retention-policies:get ID`\n\nGet information about a retention policy\n\n```\nUSAGE\n  $ box retention-policies:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the retention policy to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a retention policy\n\nEXAMPLES\n  $ box retention-policies:get 12345\n```\n\n_See code: [src/commands/retention-policies/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/retention-policies/get.js)_\n\n## `box retention-policies:update ID`\n\nUpdate a retention policy\n\n```\nUSAGE\n  $ box retention-policies:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-a <value>] [-n <value>] [--policy-type\n    finite|indefinite] [-l <value>] [--non-modifiable] [-r] [--notify-owners] [--allow-extension]\n\nARGUMENTS\n  ID  ID of the retention policy to update\n\nFLAGS\n  -a, --disposition-action=<value>  For indefinite policies, disposition action must be remove_retention\n  -h, --help                        Show CLI help\n  -l, --retention-length=<value>    The amount of time, in days, to apply the retention policy. Required for finite\n                                    policies\n  -n, --policy-name=<value>         New name of retention policy\n  -q, --quiet                       Suppress any non-error output to stderr\n  -r, --retire                      Retire a retention policy\n  -s, --save                        Save report to default reports folder on disk\n  -t, --token=<value>               Provide a token to perform this call\n  -v, --verbose                     Show verbose output, which can be helpful for debugging\n  -y, --yes                         Automatically respond yes to all confirmation prompts\n      --[no-]allow-extension        The owner of a file will be allowed to extend the retention\n      --as-user=<value>             Provide an ID for a user\n      --bulk-file-path=<value>      File path to bulk .csv or .json objects\n      --csv                         Output formatted CSV\n      --fields=<value>              Comma separated list of fields to show\n      --json                        Output formatted JSON\n      --no-color                    Turn off colors for logging\n      --non-modifiable              Set retention type to non_modifiable.\n      --[no-]notify-owners          The owner or co-owner will get notified when a file is nearing expiration\n      --policy-type=<option>        Type of policy\n                                    <options: finite|indefinite>\n      --save-to-file-path=<value>   Override default file path to save report\n\nDESCRIPTION\n  Update a retention policy\n\nEXAMPLES\n  $ box retention-policies:update 12345\n```\n\n_See code: [src/commands/retention-policies/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/retention-policies/update.js)_\n"
  },
  {
    "path": "docs/search.md",
    "content": "`box search`\n============\n\nSearch for files and folders in your Enterprise\n\n* [`box search [QUERY]`](#box-search-query)\n\n## `box search [QUERY]`\n\nSearch for files and folders in your Enterprise\n\n```\nUSAGE\n  $ box search [QUERY] [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--scope\n    user_content|enterprise_content] [--type file|folder|web_link] [--file-extensions <value>] [--mdfilter <value>... |\n    |  | ] [--content-types <value>] [--ancestor-folder-ids <value>] [--owner-user-ids <value>] [--created-at-from\n    <value>] [--created-at-to <value>] [--updated-at-from <value>] [--updated-at-to <value>] [--trash-content\n    trashed_only|non_trashed_only] [--size-from <value>] [--size-to <value>] [--direction asc|desc --sort <value>]\n    [--limit <value>] [--all] [--include-recent-shared-links]\n\nARGUMENTS\n  [QUERY]  The search term. Some queries with special characters (e.g. double quotes for exact match) may require\n           escaping (e.g. box search '\\\"query_term\\\"').\n\nFLAGS\n  -h, --help                         Show CLI help\n  -q, --quiet                        Suppress any non-error output to stderr\n  -s, --save                         Save report to default reports folder on disk\n  -t, --token=<value>                Provide a token to perform this call\n  -v, --verbose                      Show verbose output, which can be helpful for debugging\n  -y, --yes                          Automatically respond yes to all confirmation prompts\n      --all                          Returns all search results.\n      --ancestor-folder-ids=<value>  Search for the contents of specific folders (and folders within them). Requires a\n                                     folder ID or a set of comma-delimited folder IDs\n      --as-user=<value>              Provide an ID for a user\n      --bulk-file-path=<value>       File path to bulk .csv or .json objects\n      --content-types=<value>        Search for objects of specified content types. Requires a content type or a set of\n                                     comma-delimited content types\n      --created-at-from=<value>      Start of created date range. Use a RFC3339 timestamp or shorthand syntax 0t, like\n                                     5w for 5 weeks\n      --created-at-to=<value>        End of created date range. Use a RFC3339 timestamp or shorthand syntax 0t, like 5w\n                                     for 5 weeks\n      --csv                          Output formatted CSV\n      --direction=<option>           The direction to sort results (ascending or descending)\n                                     <options: asc|desc>\n      --fields=<value>               Comma separated list of fields to show\n      --file-extensions=<value>      Limit searches to specific file extensions i.e. png,md,pdf\n      --include-recent-shared-links  Returns shared links that the user recently accessed\n      --json                         Output formatted JSON\n      --limit=<value>                Defines the maximum number of items to return. Default value is 100.\n      --mdfilter=<value>...          Metadata value to filter on, in the format <scope>.<templateKey>.<field>=<value>.\n                                     For enterprise templates, scope is usually enterprise_<enterpriseID> (for example\n                                     enterprise_123456).\n      --no-color                     Turn off colors for logging\n      --owner-user-ids=<value>       Search for objects by owner. Requires a user ID or a set of comma-delimited user\n                                     IDs\n      --save-to-file-path=<value>    Override default file path to save report\n      --scope=<option>               The scope on which you want search\n                                     <options: user_content|enterprise_content>\n      --size-from=<value>            Lower bound for file size, in bytes\n      --size-to=<value>              Upper bound for file size, in bytes\n      --sort=<value>                 The field to sort results by\n      --trash-content=<option>       Controls whether to search in the trash. Defaults to non_trashed_only\n                                     <options: trashed_only|non_trashed_only>\n      --type=<option>                The type of objects you want to include in the search results\n                                     <options: file|folder|web_link>\n      --updated-at-from=<value>      Start of updated date range. Use a RFC3339 timestamp or shorthand syntax 0t, like\n                                     5w for 5 weeks\n      --updated-at-to=<value>        End of updated date range. Use a RFC3339 timestamp or shorthand syntax 0t, like 5w\n                                     for 5 weeks\n\nDESCRIPTION\n  Search for files and folders in your Enterprise\n\nEXAMPLES\n  $ box search \"Q3 OKR\"\n\n  $ box search --mdfilter \"enterprise.employeeRecord.name=John Doe\"\n```\n\n_See code: [src/commands/search.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/search.js)_\n"
  },
  {
    "path": "docs/shared-links.md",
    "content": "`box shared-links`\n==================\n\nManage shared links\n\n* [`box shared-links:create ITEMID ITEMTYPE`](#box-shared-linkscreate-itemid-itemtype)\n* [`box shared-links:delete ITEMID ITEMTYPE`](#box-shared-linksdelete-itemid-itemtype)\n* [`box shared-links:get URL`](#box-shared-linksget-url)\n* [`box shared-links:update ITEMID ITEMTYPE`](#box-shared-linksupdate-itemid-itemtype)\n\n## `box shared-links:create ITEMID ITEMTYPE`\n\nCreate a shared link for a Box item\n\n```\nUSAGE\n  $ box shared-links:create ITEMID ITEMTYPE [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--access <value>]\n    [--password <value>] [--unshared-at <value>] [--can-download] [--vanity-name <value>] [--can-edit]\n\nARGUMENTS\n  ITEMID    ID of the Box item to share\n  ITEMTYPE  (file|folder) Type of item for shared link: either file or folder\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --access=<value>             Shared link access level\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-download          Whether the shared link allows downloads\n      --[no-]can-edit              Whether the shared link allows edits. Only Applicable for files.\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --password=<value>           Shared link password\n      --save-to-file-path=<value>  Override default file path to save report\n      --unshared-at=<value>        Time that this link will become disabled. Use s for seconds, m for minutes, h for\n                                   hours, d for days, w for weeks, M for months. For example, 30 seconds is 30s from\n                                   now.\n      --vanity-name=<value>        Defines a custom vanity name to use in the shared link URL. It should be between 12\n                                   and 30 characters. This field can contains only letters, numbers and hyphens.\n\nDESCRIPTION\n  Create a shared link for a Box item\n\nALIASES\n  $ box shared-links:update\n\nEXAMPLES\n  $ box shared-links:create 22222 folder --access company --vanity-name my-custom-name-123\n```\n\n_See code: [src/commands/shared-links/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/shared-links/create.js)_\n\n## `box shared-links:delete ITEMID ITEMTYPE`\n\nDelete a shared link for a Box item\n\n```\nUSAGE\n  $ box shared-links:delete ITEMID ITEMTYPE [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ITEMID    ID of the Box item to remove the shared link from\n  ITEMTYPE  (file|folder) Type of item for shared link: either file or folder\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a shared link for a Box item\n\nEXAMPLES\n  $ box shared-links:delete 22222 folder\n```\n\n_See code: [src/commands/shared-links/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/shared-links/delete.js)_\n\n## `box shared-links:get URL`\n\nGet information from a shared item URL\n\n```\nUSAGE\n  $ box shared-links:get URL [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--password <value>]\n\nARGUMENTS\n  URL  Shared item URL to resolve\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --password=<value>           Shared item password\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information from a shared item URL\n\nEXAMPLES\n  $ box shared-links:get https://app.box.com/s/13ynxiqe3y4tup3j0yn4qairs5ebfxo3\n```\n\n_See code: [src/commands/shared-links/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/shared-links/get.js)_\n\n## `box shared-links:update ITEMID ITEMTYPE`\n\nCreate a shared link for a Box item\n\n```\nUSAGE\n  $ box shared-links:update ITEMID ITEMTYPE [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--access <value>]\n    [--password <value>] [--unshared-at <value>] [--can-download] [--vanity-name <value>] [--can-edit]\n\nARGUMENTS\n  ITEMID    ID of the Box item to share\n  ITEMTYPE  (file|folder) Type of item for shared link: either file or folder\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --access=<value>             Shared link access level\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]can-download          Whether the shared link allows downloads\n      --[no-]can-edit              Whether the shared link allows edits. Only Applicable for files.\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --password=<value>           Shared link password\n      --save-to-file-path=<value>  Override default file path to save report\n      --unshared-at=<value>        Time that this link will become disabled. Use s for seconds, m for minutes, h for\n                                   hours, d for days, w for weeks, M for months. For example, 30 seconds is 30s from\n                                   now.\n      --vanity-name=<value>        Defines a custom vanity name to use in the shared link URL. It should be between 12\n                                   and 30 characters. This field can contains only letters, numbers and hyphens.\n\nDESCRIPTION\n  Create a shared link for a Box item\n\nALIASES\n  $ box shared-links:update\n\nEXAMPLES\n  $ box shared-links:create 22222 folder --access company --vanity-name my-custom-name-123\n```\n"
  },
  {
    "path": "docs/sign-requests.md",
    "content": "`box sign-requests`\n===================\n\nList sign requests\n\n* [`box sign-requests`](#box-sign-requests)\n* [`box sign-requests:cancel ID`](#box-sign-requestscancel-id)\n* [`box sign-requests:create`](#box-sign-requestscreate)\n* [`box sign-requests:get ID`](#box-sign-requestsget-id)\n* [`box sign-requests:resend ID`](#box-sign-requestsresend-id)\n\n## `box sign-requests`\n\nList sign requests\n\n```\nUSAGE\n  $ box sign-requests [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--limit <value>] [--marker <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --limit=<value>              The maximum number of items to return per page.\n      --marker=<value>             Defines the position marker at which to begin returning results. This is used when\n                                   paginating using marker-based pagination. This requires `usemarker` to be set to\n                                   `true`.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List sign requests\n\nEXAMPLES\n  $ box sign-requests\n```\n\n_See code: [src/commands/sign-requests/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/sign-requests/index.js)_\n\n## `box sign-requests:cancel ID`\n\nCancel sign request\n\n```\nUSAGE\n  $ box sign-requests:cancel ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  The ID of the sign request\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Cancel sign request\n\nEXAMPLES\n  $ box sign-requests:cancel 12345\n```\n\n_See code: [src/commands/sign-requests/cancel.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/sign-requests/cancel.js)_\n\n## `box sign-requests:create`\n\nCreate sign request\n\n```\nUSAGE\n  $ box sign-requests:create --signer <value>... [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--source-files\n    <value>] [--parent-folder <value>] [--document-preparation-needed] [--text-signatures-enabled] [--email-subject\n    <value>] [--email-message <value>] [--reminders-enabled] [--prefill-tag <value>...] [--days-valid <value>]\n    [--external-id <value>] [--redirect-url <value>] [--declined-redirect-url <value>] [--template-id <value>]\n\nFLAGS\n  -h, --help\n      Show CLI help\n\n  -q, --quiet\n      Suppress any non-error output to stderr\n\n  -s, --save\n      Save report to default reports folder on disk\n\n  -t, --token=<value>\n      Provide a token to perform this call\n\n  -v, --verbose\n      Show verbose output, which can be helpful for debugging\n\n  -y, --yes\n      Automatically respond yes to all confirmation prompts\n\n  --as-user=<value>\n      Provide an ID for a user\n\n  --bulk-file-path=<value>\n      File path to bulk .csv or .json objects\n\n  --csv\n      Output formatted CSV\n\n  --days-valid=<value>\n      Number of days after which this request will automatically expire if not completed\n\n  --declined-redirect-url=<value>\n      The URL that a signer will be redirected to after declining to sign a document. Defining this URL overrides the\n      default redirect URL for all signers.\n\n  --[no-]document-preparation-needed\n      Indicates if the sender should receive a `prepare_url` in the response to complete document preparation via UI.\n\n  --email-message=<value>\n      Message to include in sign request email. The field is cleaned through sanitization of specific characters. However,\n      some html tags are allowed. Links included in the message are also converted to hyperlinks in the email. The message\n      may contain the following html tags including `a`, `abbr`, `acronym`, `b`, `blockquote`, `code`, `em`, `i`, `ul`,\n      `li`, `ol`, and `strong`. Be aware that when the text to html ratio is too high, the email may end up in spam\n      filters. Custom styles on these tags are not allowed. If this field is not passed, a default message will be used.\n\n  --email-subject=<value>\n      Subject of sign request email. This is cleaned by sign request. If this field is not passed, a default subject will\n      be used.\n\n  --external-id=<value>\n      This can be used to reference an ID in an external system that the sign request is related to.\n\n  --fields=<value>\n      Comma separated list of fields to show\n\n  --json\n      Output formatted JSON\n\n  --no-color\n      Turn off colors for logging\n\n  --parent-folder=<value>\n      The destination folder to place final, signed document and signing log\n\n  --prefill-tag=<value>...\n      Prefills a sign related tag in the content. Pass in a comma-separated dictionary of fields: id,text,checkbox,date.\n      Can be added multiple times.\n\n  --redirect-url=<value>\n      The URL that a signer will be redirected to after signing a document. Defining this URL overrides the default\n      redirect URL for all signers. If no declined redirect URL is specified, this URL will be used for decline actions as\n      well.\n\n  --[no-]reminders-enabled\n      Reminds signers to sign a document on day 3, 8, 13 and 18. Reminders are only sent to outstanding signers.\n\n  --save-to-file-path=<value>\n      Override default file path to save report\n\n  --signer=<value>...\n      (required) A signer for the sign request. 35 is the max number of signers permitted. Can be added multiple times.\n      Allowed (recommended) properties:\n      email,role,is-in-person,order,embed-url-external-user-id,redirect-url,declined-redirect-url,group-id but snake case\n      is also supported for: is_in_person,order,embed_url_external_user_id,redirect_url,declined_redirect_url,group_id\n\n  --source-files=<value>\n      Comma separated list of files to create a signing document from. This is currently limited to 10 files, e.g. 12345\n\n  --template-id=<value>\n      When a signature request is created from a template this field will indicate the id of that template.\n\n  --[no-]text-signatures-enabled\n      Disables the usage of signatures generated by typing (text)\n\nDESCRIPTION\n  Create sign request\n\nEXAMPLES\n  $ box sign-requests:create --signer email=alice@example.com --source-files 12345 --parent-folder 23456  --prefill-tag id=1,value=Test\n```\n\n_See code: [src/commands/sign-requests/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/sign-requests/create.js)_\n\n## `box sign-requests:get ID`\n\nGet sign request by ID\n\n```\nUSAGE\n  $ box sign-requests:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  The ID of the sign request\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get sign request by ID\n\nEXAMPLES\n  $ box sign-requests:get 12345\n```\n\n_See code: [src/commands/sign-requests/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/sign-requests/get.js)_\n\n## `box sign-requests:resend ID`\n\nResend sign request\n\n```\nUSAGE\n  $ box sign-requests:resend ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  The ID of the sign request\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Resend sign request\n\nEXAMPLES\n  $ box sign-requests:resend 12345\n```\n\n_See code: [src/commands/sign-requests/resend.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/sign-requests/resend.js)_\n"
  },
  {
    "path": "docs/sign-templates.md",
    "content": "`box sign-templates`\n====================\n\nList sign templates\n\n* [`box sign-templates`](#box-sign-templates)\n* [`box sign-templates:get ID`](#box-sign-templatesget-id)\n\n## `box sign-templates`\n\nList sign templates\n\n```\nUSAGE\n  $ box sign-templates [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--limit <value>] [--marker <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --limit=<value>              The maximum number of items to return per page.\n      --marker=<value>             Defines the position marker at which to begin returning results. This is used when\n                                   paginating using marker-based pagination. This requires `usemarker` to be set to\n                                   `true`.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List sign templates\n\nEXAMPLES\n  $ box sign-templates\n```\n\n_See code: [src/commands/sign-templates/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/sign-templates/index.js)_\n\n## `box sign-templates:get ID`\n\nGet sign template by ID\n\n```\nUSAGE\n  $ box sign-templates:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  The ID of the sign template\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get sign template by ID\n\nEXAMPLES\n  $ box sign-templates:get 12345\n```\n\n_See code: [src/commands/sign-templates/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/sign-templates/get.js)_\n"
  },
  {
    "path": "docs/storage-policies.md",
    "content": "`box storage-policies`\n======================\n\nList storage policies\n\n* [`box storage-policies`](#box-storage-policies)\n* [`box storage-policies:assign STORAGEPOLICYID USERID`](#box-storage-policiesassign-storagepolicyid-userid)\n* [`box storage-policies:assignments:get ID`](#box-storage-policiesassignmentsget-id)\n* [`box storage-policies:assignments:lookup ID`](#box-storage-policiesassignmentslookup-id)\n* [`box storage-policies:assignments:remove ID`](#box-storage-policiesassignmentsremove-id)\n* [`box storage-policies:get ID`](#box-storage-policiesget-id)\n* [`box storage-policies:list`](#box-storage-policieslist)\n\n## `box storage-policies`\n\nList storage policies\n\n```\nUSAGE\n  $ box storage-policies [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List storage policies\n\nALIASES\n  $ box storage-policies:list\n\nEXAMPLES\n  $ box storage-policies\n```\n\n_See code: [src/commands/storage-policies/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/storage-policies/index.js)_\n\n## `box storage-policies:assign STORAGEPOLICYID USERID`\n\nAssign a storage policy\n\n```\nUSAGE\n  $ box storage-policies:assign STORAGEPOLICYID USERID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  STORAGEPOLICYID  Id of the storage policy\n  USERID           Id of the user to assign the storage policy to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Assign a storage policy\n\nEXAMPLES\n  $ box storage-policies:assign 12345 33333\n```\n\n_See code: [src/commands/storage-policies/assign.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/storage-policies/assign.js)_\n\n## `box storage-policies:assignments:get ID`\n\nGet information on a storage policy assignment\n\n```\nUSAGE\n  $ box storage-policies:assignments:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the storage policy assignment to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information on a storage policy assignment\n\nEXAMPLES\n  $ box storage-policies:assignments:get 12345\n```\n\n_See code: [src/commands/storage-policies/assignments/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/storage-policies/assignments/get.js)_\n\n## `box storage-policies:assignments:lookup ID`\n\nLook up which storage policy an object is assigned to\n\n```\nUSAGE\n  $ box storage-policies:assignments:lookup ID --type user|enterprise [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s\n    | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the object to look up the storage policy for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --type=<option>              (required) [default: user] Type of object to look up the storage policy for\n                                   <options: user|enterprise>\n\nDESCRIPTION\n  Look up which storage policy an object is assigned to\n\nEXAMPLES\n  $ box storage-policies:assignments:lookup 33333\n```\n\n_See code: [src/commands/storage-policies/assignments/lookup.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/storage-policies/assignments/lookup.js)_\n\n## `box storage-policies:assignments:remove ID`\n\nDelete a storage policy assignment\n\n```\nUSAGE\n  $ box storage-policies:assignments:remove ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the storage policy assignment to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a storage policy assignment\n\nEXAMPLES\n  $ box storage-policies:assignments:remove 12345\n```\n\n_See code: [src/commands/storage-policies/assignments/remove.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/storage-policies/assignments/remove.js)_\n\n## `box storage-policies:get ID`\n\nGet information on a storage policy\n\n```\nUSAGE\n  $ box storage-policies:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the storage policy to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information on a storage policy\n\nEXAMPLES\n  $ box storage-policies:get 12345\n```\n\n_See code: [src/commands/storage-policies/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/storage-policies/get.js)_\n\n## `box storage-policies:list`\n\nList storage policies\n\n```\nUSAGE\n  $ box storage-policies:list [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List storage policies\n\nALIASES\n  $ box storage-policies:list\n\nEXAMPLES\n  $ box storage-policies\n```\n"
  },
  {
    "path": "docs/tasks.md",
    "content": "`box tasks`\n===========\n\nManage tasks\n\n* [`box tasks:assign TASKID`](#box-tasksassign-taskid)\n* [`box tasks:assignments ID`](#box-tasksassignments-id)\n* [`box tasks:assignments:delete ID`](#box-tasksassignmentsdelete-id)\n* [`box tasks:assignments:get ID`](#box-tasksassignmentsget-id)\n* [`box tasks:assignments:update ID`](#box-tasksassignmentsupdate-id)\n* [`box tasks:create FILEID`](#box-taskscreate-fileid)\n* [`box tasks:delete ID`](#box-tasksdelete-id)\n* [`box tasks:get ID`](#box-tasksget-id)\n* [`box tasks:update ID`](#box-tasksupdate-id)\n\n## `box tasks:assign TASKID`\n\nCreate a task assignment\n\n```\nUSAGE\n  $ box tasks:assign TASKID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--assign-to-user-id\n    <value> | --assign-to-user-login <value>]\n\nARGUMENTS\n  TASKID  ID of the task to assign\n\nFLAGS\n  -h, --help                          Show CLI help\n  -q, --quiet                         Suppress any non-error output to stderr\n  -s, --save                          Save report to default reports folder on disk\n  -t, --token=<value>                 Provide a token to perform this call\n  -v, --verbose                       Show verbose output, which can be helpful for debugging\n  -y, --yes                           Automatically respond yes to all confirmation prompts\n      --as-user=<value>               Provide an ID for a user\n      --assign-to-user-id=<value>     Assign task by user ID\n      --assign-to-user-login=<value>  Assign task by user login\n      --bulk-file-path=<value>        File path to bulk .csv or .json objects\n      --csv                           Output formatted CSV\n      --fields=<value>                Comma separated list of fields to show\n      --json                          Output formatted JSON\n      --no-color                      Turn off colors for logging\n      --save-to-file-path=<value>     Override default file path to save report\n\nDESCRIPTION\n  Create a task assignment\n\nALIASES\n  $ box task-assignments:create\n\nEXAMPLES\n  $ box tasks:assign 88888 --assign-to-user-id 33333\n```\n\n_See code: [src/commands/tasks/assign.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/tasks/assign.js)_\n\n## `box tasks:assignments ID`\n\nList all task assignments on a task\n\n```\nUSAGE\n  $ box tasks:assignments ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the task to get assignments for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all task assignments on a task\n\nALIASES\n  $ box task-assignments:list\n\nEXAMPLES\n  $ box tasks:assignments 88888\n```\n\n_See code: [src/commands/tasks/assignments/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/tasks/assignments/index.js)_\n\n## `box tasks:assignments:delete ID`\n\nDelete a task assignment\n\n```\nUSAGE\n  $ box tasks:assignments:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the task assignment to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a task assignment\n\nALIASES\n  $ box task-assignments:delete\n\nEXAMPLES\n  $ box tasks:assignments:delete 12345\n```\n\n_See code: [src/commands/tasks/assignments/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/tasks/assignments/delete.js)_\n\n## `box tasks:assignments:get ID`\n\nGet information about a task assignment\n\n```\nUSAGE\n  $ box tasks:assignments:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the task assignment to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a task assignment\n\nALIASES\n  $ box task-assignments:get\n\nEXAMPLES\n  $ box tasks:assignments:get 12345\n```\n\n_See code: [src/commands/tasks/assignments/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/tasks/assignments/get.js)_\n\n## `box tasks:assignments:update ID`\n\nUpdate a task assignment\n\n```\nUSAGE\n  $ box tasks:assignments:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--message <value>] [--status\n    completed|incomplete|approved|rejected |  |  |  | ]\n\nARGUMENTS\n  ID  ID of the task assignment to update\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --message=<value>            A message from the assignee about this task\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --status=<option>            Set the resolution state of the task assignment\n                                   <options: completed|incomplete|approved|rejected>\n\nDESCRIPTION\n  Update a task assignment\n\nALIASES\n  $ box task-assignments:update\n\nEXAMPLES\n  $ box tasks:assignments:update 12345 --status approved\n```\n\n_See code: [src/commands/tasks/assignments/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/tasks/assignments/update.js)_\n\n## `box tasks:create FILEID`\n\nCreate a task on a file\n\n```\nUSAGE\n  $ box tasks:create FILEID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--message <value>]\n    [--due-at <value>] [--id-only] [--completion-rule all_assignees|any_assignee]\n\nARGUMENTS\n  FILEID  ID of the file to create a task on\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --completion-rule=<option>   Rule for how many assignees must complete the task to consider it completed\n                                   <options: all_assignees|any_assignee>\n      --csv                        Output formatted CSV\n      --due-at=<value>             When this task is due, use format 05h for 5 hours for example\n      --fields=<value>             Comma separated list of fields to show\n      --id-only                    Return only an ID to output from this command\n      --json                       Output formatted JSON\n      --message=<value>            Message for task\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Create a task on a file\n\nEXAMPLES\n  $ box tasks:create 11111 --message \"Please proofread this document\"\n```\n\n_See code: [src/commands/tasks/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/tasks/create.js)_\n\n## `box tasks:delete ID`\n\nDelete a task\n\n```\nUSAGE\n  $ box tasks:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the task to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a task\n\nEXAMPLES\n  $ box tasks:delete 88888\n```\n\n_See code: [src/commands/tasks/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/tasks/delete.js)_\n\n## `box tasks:get ID`\n\nGet information about a task\n\n```\nUSAGE\n  $ box tasks:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the task to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a task\n\nEXAMPLES\n  $ box tasks:get 88888\n```\n\n_See code: [src/commands/tasks/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/tasks/get.js)_\n\n## `box tasks:update ID`\n\nUpdate a task on a file\n\n```\nUSAGE\n  $ box tasks:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--message <value>] [--due-at <value>]\n    [--completion-rule all_assignees|any_assignee]\n\nARGUMENTS\n  ID  ID of the task to update\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --completion-rule=<option>   Rule for how many assignees must complete the task to consider it completed\n                                   <options: all_assignees|any_assignee>\n      --csv                        Output formatted CSV\n      --due-at=<value>             When this task is due, use format 05h for 5 hours for example\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --message=<value>            Message for task\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Update a task on a file\n\nEXAMPLES\n  $ box tasks:update 88888 --due-at 1w\n```\n\n_See code: [src/commands/tasks/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/tasks/update.js)_\n"
  },
  {
    "path": "docs/terms-of-service.md",
    "content": "`box terms-of-service`\n======================\n\nList terms of services for your enterprise\n\n* [`box terms-of-service`](#box-terms-of-service)\n* [`box terms-of-service:create`](#box-terms-of-servicecreate)\n* [`box terms-of-service:get ID`](#box-terms-of-serviceget-id)\n* [`box terms-of-service:get-user-status TOSID`](#box-terms-of-serviceget-user-status-tosid)\n* [`box terms-of-service:set-user-status ID`](#box-terms-of-serviceset-user-status-id)\n* [`box terms-of-service:update ID`](#box-terms-of-serviceupdate-id)\n\n## `box terms-of-service`\n\nList terms of services for your enterprise\n\n```\nUSAGE\n  $ box terms-of-service [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--type managed|external]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --type=<option>              Filter by terms of service type\n                                   <options: managed|external>\n\nDESCRIPTION\n  List terms of services for your enterprise\n\nEXAMPLES\n  $ box terms-of-service\n```\n\n_See code: [src/commands/terms-of-service/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/terms-of-service/index.js)_\n\n## `box terms-of-service:create`\n\nCreate a terms of service\n\n```\nUSAGE\n  $ box terms-of-service:create --type managed|external --status enabled|disabled --text <value> [-t <value>] [--as-user\n    <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path\n    <value>] [-h] [-v] [-y] [-q]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --status=<option>            (required) Status of the terms of service\n                                   <options: enabled|disabled>\n      --text=<value>               (required) Text for the terms of service\n      --type=<option>              (required) Type of terms of service\n                                   <options: managed|external>\n\nDESCRIPTION\n  Create a terms of service\n\nEXAMPLES\n  $ box terms-of-service:create --type external --status enabled --text \"By using this service, you agree to....\"\n```\n\n_See code: [src/commands/terms-of-service/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/terms-of-service/create.js)_\n\n## `box terms-of-service:get ID`\n\nGet information on a terms of service\n\n```\nUSAGE\n  $ box terms-of-service:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID for the terms of service to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information on a terms of service\n\nEXAMPLES\n  $ box terms-of-service:get 55555\n```\n\n_See code: [src/commands/terms-of-service/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/terms-of-service/get.js)_\n\n## `box terms-of-service:get-user-status TOSID`\n\nGet a user's status on a terms of service\n\n```\nUSAGE\n  $ box terms-of-service:get-user-status TOSID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--user-id <value>]\n\nARGUMENTS\n  TOSID  ID of the terms of service to get user status for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --user-id=<value>            ID for a user to get status for; defaults to the current user ID\n\nDESCRIPTION\n  Get a user's status on a terms of service\n\nEXAMPLES\n  $ box terms-of-service:get-user-status 55555\n```\n\n_See code: [src/commands/terms-of-service/get-user-status.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/terms-of-service/get-user-status.js)_\n\n## `box terms-of-service:set-user-status ID`\n\nSet a user's status on a terms of service with a terms of service Id\n\n```\nUSAGE\n  $ box terms-of-service:set-user-status ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--accept | --reject] [--user-id <value>]\n\nARGUMENTS\n  ID  ID of the terms of service to set the user status on\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --accept                     Set the user's status as accepted\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --reject                     Set the user's status as rejected\n      --save-to-file-path=<value>  Override default file path to save report\n      --user-id=<value>            ID of the user to set status for; defaults to the current user\n\nDESCRIPTION\n  Set a user's status on a terms of service with a terms of service Id\n\nEXAMPLES\n  $ box terms-of-service:set-user-status 55555 --accept\n```\n\n_See code: [src/commands/terms-of-service/set-user-status.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/terms-of-service/set-user-status.js)_\n\n## `box terms-of-service:update ID`\n\nUpdate a terms of service\n\n```\nUSAGE\n  $ box terms-of-service:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--status enabled|disabled] [--text\n    <value>]\n\nARGUMENTS\n  ID  ID of the terms of service to update\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --status=<option>            Status of the terms of service\n                                   <options: enabled|disabled>\n      --text=<value>               Text for the terms of service\n\nDESCRIPTION\n  Update a terms of service\n\nEXAMPLES\n  $ box terms-of-service:update 55555 --status disabled\n```\n\n_See code: [src/commands/terms-of-service/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/terms-of-service/update.js)_\n"
  },
  {
    "path": "docs/tokens.md",
    "content": "`box tokens`\n============\n\nGet a token. Returns the service account token by default\n\n* [`box tokens:exchange SCOPE`](#box-tokensexchange-scope)\n* [`box tokens:get`](#box-tokensget)\n* [`box tokens:revoke TOKEN`](#box-tokensrevoke-token)\n\n## `box tokens:exchange SCOPE`\n\nGet a token. Returns the service account token by default\n\n```\nUSAGE\n  $ box tokens:exchange SCOPE [--no-color] [-h] [-v] [-q] [-u <value> | -t <value>] [--file-id <value> | --folder-id\n    <value>]\n\nARGUMENTS\n  SCOPE  The scope(s) for the new token, separated by a comma if multiple are present\n\nFLAGS\n  -h, --help               Show CLI help\n  -q, --quiet              Suppress any non-error output to stderr\n  -t, --token=<value>      Specify the token to exchange\n  -u, --user-id=<value>    Get a user token from a user ID\n  -v, --verbose            Show verbose output, which can be helpful for debugging\n      --file-id=<value>    Scope the token to a specific file\n      --folder-id=<value>  Scope the token to a specific folder\n      --no-color           Turn off colors for logging\n\nDESCRIPTION\n  Get a token. Returns the service account token by default\n```\n\n_See code: [src/commands/tokens/exchange.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/tokens/exchange.js)_\n\n## `box tokens:get`\n\nGenerate a new access token. Returns a service account token for the default environment unless --user-id is specified.\n\n```\nUSAGE\n  $ box tokens:get [--no-color] [-h] [-v] [-q] [-u <value>]\n\nFLAGS\n  -h, --help             Show CLI help\n  -q, --quiet            Suppress any non-error output to stderr\n  -u, --user-id=<value>  Generate a user token for the specified user ID\n  -v, --verbose          Show verbose output, which can be helpful for debugging\n      --no-color         Turn off colors for logging\n\nDESCRIPTION\n  Generate a new access token. Returns a service account token for the default environment unless --user-id is\n  specified.\n\nEXAMPLES\n  $ box tokens:get\n\n  $ box tokens:get --user-id 12345\n```\n\n_See code: [src/commands/tokens/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/tokens/get.js)_\n\n## `box tokens:revoke TOKEN`\n\nRevoke a token.  The token will no longer be valid for making API calls.\n\n```\nUSAGE\n  $ box tokens:revoke TOKEN [--no-color] [-h] [-v] [-q]\n\nARGUMENTS\n  TOKEN  The token to revoke\n\nFLAGS\n  -h, --help      Show CLI help\n  -q, --quiet     Suppress any non-error output to stderr\n  -v, --verbose   Show verbose output, which can be helpful for debugging\n      --no-color  Turn off colors for logging\n\nDESCRIPTION\n  Revoke a token.  The token will no longer be valid for making API calls.\n```\n\n_See code: [src/commands/tokens/revoke.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/tokens/revoke.js)_\n"
  },
  {
    "path": "docs/trash.md",
    "content": "`box trash`\n===========\n\nList all items in trash\n\n* [`box trash`](#box-trash)\n* [`box trash:delete TYPE ID`](#box-trashdelete-type-id)\n* [`box trash:get TYPE ID`](#box-trashget-type-id)\n* [`box trash:list`](#box-trashlist)\n* [`box trash:restore TYPE ID`](#box-trashrestore-type-id)\n\n## `box trash`\n\nList all items in trash\n\n```\nUSAGE\n  $ box trash [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all items in trash\n\nALIASES\n  $ box trash:list\n\nEXAMPLES\n  $ box trash\n```\n\n_See code: [src/commands/trash/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/trash/index.js)_\n\n## `box trash:delete TYPE ID`\n\nPermanently delete an item\n\n```\nUSAGE\n  $ box trash:delete TYPE ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  TYPE  (file|folder|web_link) Type of the item to permanently delete\n  ID    ID of the item to permanently delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Permanently delete an item\n\nEXAMPLES\n  $ box trash:delete folder 22222\n```\n\n_See code: [src/commands/trash/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/trash/delete.js)_\n\n## `box trash:get TYPE ID`\n\nGet information about an item in trash\n\n```\nUSAGE\n  $ box trash:get TYPE ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  TYPE  (file|folder|web_link) Type of the item to get\n  ID    ID of the item to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about an item in trash\n\nEXAMPLES\n  $ box trash:get folder 22222\n```\n\n_See code: [src/commands/trash/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/trash/get.js)_\n\n## `box trash:list`\n\nList all items in trash\n\n```\nUSAGE\n  $ box trash:list [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all items in trash\n\nALIASES\n  $ box trash:list\n\nEXAMPLES\n  $ box trash\n```\n\n## `box trash:restore TYPE ID`\n\nRestore an item from trash\n\n```\nUSAGE\n  $ box trash:restore TYPE ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--name <value>]\n    [--parent-id <value>]\n\nARGUMENTS\n  TYPE  (file|folder|web_link) Type of the item to restore\n  ID    ID of the item to restore\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --name=<value>               The new name for the item\n      --no-color                   Turn off colors for logging\n      --parent-id=<value>          ID of a folder to restore the item to only when the original folder no longer exists\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Restore an item from trash\n\nEXAMPLES\n  $ box trash:restore folder 22222\n```\n\n_See code: [src/commands/trash/restore.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/trash/restore.js)_\n"
  },
  {
    "path": "docs/update.md",
    "content": "`box update`\n============\n\nUpdate the BoxCLI using GitHub\n\n* [`box update`](#box-update)\n\n## `box update`\n\nUpdate the BoxCLI using GitHub\n\n```\nUSAGE\n  $ box update [-a] [-v <value> | -i] [--force]\n\nFLAGS\n  -a, --available        Install a specific version.\n  -i, --interactive      Interactively select version to install. This is ignored if a channel is provided.\n  -v, --version=<value>  Install a specific version.\n      --force            Force a re-download of the requested version.\n\nDESCRIPTION\n  Update the BoxCLI using GitHub\n\nEXAMPLES\n  Update to a specific version:\n\n    $ box update --version 1.0.0\n\n  Interactively select version:\n\n    $ box update --interactive\n\n  See available versions:\n\n    $ box update --available\n```\n\n_See code: [src/commands/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/update.js)_\n"
  },
  {
    "path": "docs/users.md",
    "content": "`box users`\n===========\n\nList all Box users\n\n* [`box users`](#box-users)\n* [`box users:add-email-alias USERID EMAIL`](#box-usersadd-email-alias-userid-email)\n* [`box users:create NAME [LOGIN]`](#box-userscreate-name-login)\n* [`box users:delete ID`](#box-usersdelete-id)\n* [`box users:delete-email-alias USERID ALIASID`](#box-usersdelete-email-alias-userid-aliasid)\n* [`box users:email-aliases USERID`](#box-usersemail-aliases-userid)\n* [`box users:email-aliases:add USERID EMAIL`](#box-usersemail-aliasesadd-userid-email)\n* [`box users:email-aliases:remove USERID ALIASID`](#box-usersemail-aliasesremove-userid-aliasid)\n* [`box users:get [ID]`](#box-usersget-id)\n* [`box users:get-email-aliases USERID`](#box-usersget-email-aliases-userid)\n* [`box users:groups ID`](#box-usersgroups-id)\n* [`box users:invite EMAIL ENTERPRISEID`](#box-usersinvite-email-enterpriseid)\n* [`box users:invite-user EMAIL ENTERPRISEID`](#box-usersinvite-user-email-enterpriseid)\n* [`box users:list`](#box-userslist)\n* [`box users:list-groups ID`](#box-userslist-groups-id)\n* [`box users:move-root-content USERID NEWUSERID`](#box-usersmove-root-content-userid-newuserid)\n* [`box users:search NAME`](#box-userssearch-name)\n* [`box users:terminate-session`](#box-usersterminate-session)\n* [`box users:transfer-content USERID NEWUSERID`](#box-userstransfer-content-userid-newuserid)\n* [`box users:update ID`](#box-usersupdate-id)\n\n## `box users`\n\nList all Box users\n\n```\nUSAGE\n  $ box users [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [-e | [-m |\n    --app-users | -a] | ] [--filter <value> | ]\n\nFLAGS\n  -a, --all-users                  Results from all users\n  -e, --external-users             Limit results to external users only\n  -h, --help                       Show CLI help\n  -m, --managed-users              Limit results to managed users only\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --app-users                  Limit results to app users only\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --filter=<value>             Search term to filter users on; matches prefixes of user name and login fields\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all Box users\n\nALIASES\n  $ box users:list\n\nEXAMPLES\n  $ box users\n```\n\n_See code: [src/commands/users/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/users/index.js)_\n\n## `box users:add-email-alias USERID EMAIL`\n\nAdd a new email alias to a user\n\n```\nUSAGE\n  $ box users:add-email-alias USERID EMAIL [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--confirm]\n\nARGUMENTS\n  USERID  User ID to add email alias\n  EMAIL   Email to add as alias\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]confirm               Whether or not to confirm the email alias.  Only Admins may automatically confirm an\n                                   alias.\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Add a new email alias to a user\n\nALIASES\n  $ box users:add-email-alias\n\nEXAMPLES\n  $ box users:email-aliases:add 33333 user+alias@example.com\n```\n\n## `box users:create NAME [LOGIN]`\n\nCreate a new Box User\n\n```\nUSAGE\n  $ box users:create NAME [LOGIN] [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--external-id\n    <value> --app-user] [--id-only] [--sync-enable | ] [--exempt-from-device-limits] [--exempt-from-2fa]\n    [--restrict-external-collab] [--can-see-managed-users] [--password-reset] [-r user|coadmin] [-l <value>] [-j\n    <value>] [-p <value>] [-a <value>] [-d <value>] [-S active|inactive|cannot_delete_edit|cannot_delete_edit_upload]\n    [--timezone <value>] [--tracking-codes <value>]\n\nARGUMENTS\n  NAME     The user's name\n  [LOGIN]  The user's email address, not required when creating app users\n\nFLAGS\n  -S, --status=<option>                 User status\n                                        <options: active|inactive|cannot_delete_edit|cannot_delete_edit_upload>\n  -a, --address=<value>                 Address of the user\n  -d, --disk-space=<value>              User's available storage in bytes. Value of -1 grants unlimited storage\n  -h, --help                            Show CLI help\n  -j, --job-title=<value>               Job title of the user\n  -l, --language=<value>                Language of the user (ISO 639-1 Language Code).\n                                        https://developer.box.com/v2.0/docs/api-language-codes\n  -p, --phone-number=<value>            Phone number of the user\n  -q, --quiet                           Suppress any non-error output to stderr\n  -r, --role=<option>                   Role of user. Enter user or coadmin\n                                        <options: user|coadmin>\n  -s, --save                            Save report to default reports folder on disk\n  -t, --token=<value>                   Provide a token to perform this call\n  -v, --verbose                         Show verbose output, which can be helpful for debugging\n  -y, --yes                             Automatically respond yes to all confirmation prompts\n      --app-user                        Set this user as an app user\n      --as-user=<value>                 Provide an ID for a user\n      --bulk-file-path=<value>          File path to bulk .csv or .json objects\n      --[no-]can-see-managed-users      User can see managed users\n      --csv                             Output formatted CSV\n      --[no-]exempt-from-2fa            Exempt user from two-factor auth\n      --[no-]exempt-from-device-limits  Exempt user from device limits\n      --external-id=<value>             External ID for app users\n      --fields=<value>                  Comma separated list of fields to show\n      --id-only                         Return only an ID to output from this command\n      --json                            Output formatted JSON\n      --no-color                        Turn off colors for logging\n      --password-reset                  Force the user to reset password\n      --[no-]restrict-external-collab   Restrict user from external collaboration\n      --save-to-file-path=<value>       Override default file path to save report\n      --[no-]sync-enable                Enable Box Sync for this user\n      --timezone=<value>                The user's timezone. Input format follows tz database timezones\n      --tracking-codes=<value>          Comma-separated list of key-value pairs to associate with the user. Format is\n                                        name=value,name=value\n\nDESCRIPTION\n  Create a new Box User\n\nEXAMPLES\n  $ box users:create \"John Doe\" jdoe@example.com\n```\n\n_See code: [src/commands/users/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/users/create.js)_\n\n## `box users:delete ID`\n\nDelete a Box User\n\n```\nUSAGE\n  $ box users:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--notify] [-f]\n\nARGUMENTS\n  ID  User ID to delete\n\nFLAGS\n  -f, --force                      Delete user even if they own files\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --[no-]notify                The user should be notified\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a Box User\n\nEXAMPLES\n  $ box users:delete 33333\n```\n\n_See code: [src/commands/users/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/users/delete.js)_\n\n## `box users:delete-email-alias USERID ALIASID`\n\nDelete an email alias from a user\n\n```\nUSAGE\n  $ box users:delete-email-alias USERID ALIASID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  USERID   User ID to get email aliases\n  ALIASID  The ID of the email alias to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete an email alias from a user\n\nALIASES\n  $ box users:delete-email-alias\n\nEXAMPLES\n  $ box users:email-aliases:remove 33333 12345\n```\n\n## `box users:email-aliases USERID`\n\nGet all Email Aliases for a User\n\n```\nUSAGE\n  $ box users:email-aliases USERID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  USERID  User ID to get email aliases for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get all Email Aliases for a User\n\nALIASES\n  $ box users:get-email-aliases\n\nEXAMPLES\n  $ box users:email-aliases 33333\n```\n\n_See code: [src/commands/users/email-aliases/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/users/email-aliases/index.js)_\n\n## `box users:email-aliases:add USERID EMAIL`\n\nAdd a new email alias to a user\n\n```\nUSAGE\n  $ box users:email-aliases:add USERID EMAIL [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--confirm]\n\nARGUMENTS\n  USERID  User ID to add email alias\n  EMAIL   Email to add as alias\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --[no-]confirm               Whether or not to confirm the email alias.  Only Admins may automatically confirm an\n                                   alias.\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Add a new email alias to a user\n\nALIASES\n  $ box users:add-email-alias\n\nEXAMPLES\n  $ box users:email-aliases:add 33333 user+alias@example.com\n```\n\n_See code: [src/commands/users/email-aliases/add.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/users/email-aliases/add.js)_\n\n## `box users:email-aliases:remove USERID ALIASID`\n\nDelete an email alias from a user\n\n```\nUSAGE\n  $ box users:email-aliases:remove USERID ALIASID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  USERID   User ID to get email aliases\n  ALIASID  The ID of the email alias to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete an email alias from a user\n\nALIASES\n  $ box users:delete-email-alias\n\nEXAMPLES\n  $ box users:email-aliases:remove 33333 12345\n```\n\n_See code: [src/commands/users/email-aliases/remove.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/users/email-aliases/remove.js)_\n\n## `box users:get [ID]`\n\nGet information about a Box user\n\n```\nUSAGE\n  $ box users:get [ID] [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  [ID]  [default: me] ID of the user to get; defaults to the current user\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a Box user\n\nEXAMPLES\n  $ box users:get 33333\n```\n\n_See code: [src/commands/users/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/users/get.js)_\n\n## `box users:get-email-aliases USERID`\n\nGet all Email Aliases for a User\n\n```\nUSAGE\n  $ box users:get-email-aliases USERID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  USERID  User ID to get email aliases for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get all Email Aliases for a User\n\nALIASES\n  $ box users:get-email-aliases\n\nEXAMPLES\n  $ box users:email-aliases 33333\n```\n\n## `box users:groups ID`\n\nList groups a user belongs to\n\n```\nUSAGE\n  $ box users:groups ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  ID  ID of the user to get groups for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List groups a user belongs to\n\nALIASES\n  $ box users:list-groups\n\nEXAMPLES\n  $ box users:groups 33333\n```\n\n_See code: [src/commands/users/groups.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/users/groups.js)_\n\n## `box users:invite EMAIL ENTERPRISEID`\n\nInvite an Existing Box User to Your Enterprise\n\n```\nUSAGE\n  $ box users:invite EMAIL ENTERPRISEID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  EMAIL         Email address of the user to invite\n  ENTERPRISEID  ID of the Enterprise to invite the user to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Invite an Existing Box User to Your Enterprise\n\nALIASES\n  $ box users:invite-user\n\nEXAMPLES\n  $ box users:invite user@example.com 12345\n```\n\n_See code: [src/commands/users/invite.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/users/invite.js)_\n\n## `box users:invite-user EMAIL ENTERPRISEID`\n\nInvite an Existing Box User to Your Enterprise\n\n```\nUSAGE\n  $ box users:invite-user EMAIL ENTERPRISEID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  EMAIL         Email address of the user to invite\n  ENTERPRISEID  ID of the Enterprise to invite the user to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Invite an Existing Box User to Your Enterprise\n\nALIASES\n  $ box users:invite-user\n\nEXAMPLES\n  $ box users:invite user@example.com 12345\n```\n\n## `box users:list`\n\nList all Box users\n\n```\nUSAGE\n  $ box users:list [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>] [-e | [-m |\n    --app-users | -a] | ] [--filter <value> | ]\n\nFLAGS\n  -a, --all-users                  Results from all users\n  -e, --external-users             Limit results to external users only\n  -h, --help                       Show CLI help\n  -m, --managed-users              Limit results to managed users only\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --app-users                  Limit results to app users only\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --filter=<value>             Search term to filter users on; matches prefixes of user name and login fields\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all Box users\n\nALIASES\n  $ box users:list\n\nEXAMPLES\n  $ box users\n```\n\n## `box users:list-groups ID`\n\nList groups a user belongs to\n\n```\nUSAGE\n  $ box users:list-groups ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nARGUMENTS\n  ID  ID of the user to get groups for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List groups a user belongs to\n\nALIASES\n  $ box users:list-groups\n\nEXAMPLES\n  $ box users:groups 33333\n```\n\n## `box users:move-root-content USERID NEWUSERID`\n\nMove a user's root content to another user\n\n```\nUSAGE\n  $ box users:move-root-content USERID NEWUSERID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--notify]\n\nARGUMENTS\n  USERID     User whose content should be moved\n  NEWUSERID  User to whom the content should be moved\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --[no-]notify                Notify the user that their content has been moved\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Move a user's root content to another user\n\nALIASES\n  $ box users:move-root-content\n\nEXAMPLES\n  $ box users:transfer-content 33333 44444\n```\n\n## `box users:search NAME`\n\nSearch for Box users\n\n```\nUSAGE\n  $ box users:search NAME [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-e | [-m |  | -a] | ]\n\nARGUMENTS\n  NAME  Name of user to search for\n\nFLAGS\n  -a, --all-users                  Results from all users\n  -e, --external-users             Limit results to external users only\n  -h, --help                       Show CLI help\n  -m, --managed-users              Limit results to managed users only\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Search for Box users\n\nEXAMPLES\n  $ box users:search \"John Doe\"\n```\n\n_See code: [src/commands/users/search.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/users/search.js)_\n\n## `box users:terminate-session`\n\nValidates the roles and permissions of the user, and creates asynchronous jobs to terminate the user's sessions.\n\n```\nUSAGE\n  $ box users:terminate-session [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--user-ids <value>...] [--user-logins\n    <value>...]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n      --user-ids=<value>...        A list of user IDs\n      --user-logins=<value>...     A list of user logins\n\nDESCRIPTION\n  Validates the roles and permissions of the user, and creates asynchronous jobs to terminate the user's sessions.\n\nEXAMPLES\n  $ box users:terminate-session --user-ids 123 345 --user-logins abc@example.com def@example.com\n```\n\n_See code: [src/commands/users/terminate-session.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/users/terminate-session.js)_\n\n## `box users:transfer-content USERID NEWUSERID`\n\nMove a user's root content to another user\n\n```\nUSAGE\n  $ box users:transfer-content USERID NEWUSERID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--notify]\n\nARGUMENTS\n  USERID     User whose content should be moved\n  NEWUSERID  User to whom the content should be moved\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --[no-]notify                Notify the user that their content has been moved\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Move a user's root content to another user\n\nALIASES\n  $ box users:move-root-content\n\nEXAMPLES\n  $ box users:transfer-content 33333 44444\n```\n\n_See code: [src/commands/users/transfer-content.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/users/transfer-content.js)_\n\n## `box users:update ID`\n\nUpdate a Box User\n\n```\nUSAGE\n  $ box users:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--remove] [-n <value>] [--sync-enable]\n    [--exempt-from-device-limits] [--exempt-from-2fa] [--restrict-external-collab] [--can-see-managed-users]\n    [--password-reset] [-r user|coadmin] [-l <value>] [-j <value>] [-p <value>] [-a <value>] [-d <value>] [-S\n    active|inactive|cannot_delete_edit|cannot_delete_edit_upload] [--timezone <value>] [--login <value>] [--external-id\n    <value>] [--tracking-codes <value>] [--notification-email <value>]\n\nARGUMENTS\n  ID  User ID to update\n\nFLAGS\n  -S, --status=<option>                 User status. Enter active, inactive, cannot_delete_edit, or\n                                        cannot_delete_edit_upload\n                                        <options: active|inactive|cannot_delete_edit|cannot_delete_edit_upload>\n  -a, --address=<value>                 Address of the user\n  -d, --disk-space=<value>              User's available storage in bytes. Value of -1 grants unlimited storage\n  -h, --help                            Show CLI help\n  -j, --job-title=<value>               Job title of the user\n  -l, --language=<value>                Language of the user (ISO 639-1 Language Code).\n                                        https://developer.box.com/v2.0/docs/api-language-codes\n  -n, --name=<value>                    Set the user's name\n  -p, --phone-number=<value>            Phone number of the user\n  -q, --quiet                           Suppress any non-error output to stderr\n  -r, --role=<option>                   Role of user. Enter user or coadmin\n                                        <options: user|coadmin>\n  -s, --save                            Save report to default reports folder on disk\n  -t, --token=<value>                   Provide a token to perform this call\n  -v, --verbose                         Show verbose output, which can be helpful for debugging\n  -y, --yes                             Automatically respond yes to all confirmation prompts\n      --as-user=<value>                 Provide an ID for a user\n      --bulk-file-path=<value>          File path to bulk .csv or .json objects\n      --[no-]can-see-managed-users      User can see managed users\n      --csv                             Output formatted CSV\n      --[no-]exempt-from-2fa            Exempt user from two-factor auth\n      --[no-]exempt-from-device-limits  Exempt user from device limits\n      --external-id=<value>             External ID for app users\n      --fields=<value>                  Comma separated list of fields to show\n      --json                            Output formatted JSON\n      --login=<value>                   Change the user's primary email address used for logging into Box\n      --no-color                        Turn off colors for logging\n      --notification-email=<value>      Notification email address for the user, set to empty string to remove\n      --password-reset                  Force the user to reset password\n      --remove                          Remove the user from the enterprise, convert to free account\n      --[no-]restrict-external-collab   Restrict user from external collaboration\n      --save-to-file-path=<value>       Override default file path to save report\n      --[no-]sync-enable                Enable Box Sync for this user\n      --timezone=<value>                The user's timezone. Input format follows tz database timezones\n      --tracking-codes=<value>          Comma-separated list of key-value pairs to associate with the user. Format is\n                                        name=value,name=value\n\nDESCRIPTION\n  Update a Box User\n\nEXAMPLES\n  $ box users:update 33333 --status inactive\n```\n\n_See code: [src/commands/users/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/users/update.js)_\n"
  },
  {
    "path": "docs/version.md",
    "content": "`box version`\n=============\n\n\n\n* [`box version`](#box-version)\n\n## `box version`\n\n```\nUSAGE\n  $ box version [--json] [--verbose]\n\nFLAGS\n  --verbose  Show additional information about the CLI.\n\nGLOBAL FLAGS\n  --json  Format output as json.\n\nFLAG DESCRIPTIONS\n  --verbose  Show additional information about the CLI.\n\n    Additionally shows the architecture, node version, operating system, and versions of plugins that the CLI is using.\n```\n\n_See code: [@oclif/plugin-version](https://github.com/oclif/plugin-version/blob/v2.2.36/src/commands/version.js)_\n"
  },
  {
    "path": "docs/watermarking.md",
    "content": "`box watermarking`\n==================\n\nApply a watermark on an item\n\n* [`box watermarking:apply ITEMTYPE ITEMID`](#box-watermarkingapply-itemtype-itemid)\n* [`box watermarking:get ITEMTYPE ITEMID`](#box-watermarkingget-itemtype-itemid)\n* [`box watermarking:remove ITEMTYPE ITEMID`](#box-watermarkingremove-itemtype-itemid)\n\n## `box watermarking:apply ITEMTYPE ITEMID`\n\nApply a watermark on an item\n\n```\nUSAGE\n  $ box watermarking:apply ITEMTYPE ITEMID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ITEMTYPE  (file|folder) Type of item to apply a watermark to\n  ITEMID    ID of the item to apply a watermark to\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Apply a watermark on an item\n\nEXAMPLES\n  $ box watermarking:apply folder 22222\n```\n\n_See code: [src/commands/watermarking/apply.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/watermarking/apply.js)_\n\n## `box watermarking:get ITEMTYPE ITEMID`\n\nGet the watermark on an item\n\n```\nUSAGE\n  $ box watermarking:get ITEMTYPE ITEMID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ITEMTYPE  (file|folder) Type of item to get watermark for\n  ITEMID    ID of the item to get watermark for\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get the watermark on an item\n\nEXAMPLES\n  $ box watermarking:get folder 22222\n```\n\n_See code: [src/commands/watermarking/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/watermarking/get.js)_\n\n## `box watermarking:remove ITEMTYPE ITEMID`\n\nRemove a watermark from an item\n\n```\nUSAGE\n  $ box watermarking:remove ITEMTYPE ITEMID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ITEMTYPE  (file|folder) Type of item to remove watermark from\n  ITEMID    ID of the item to remove watermark from\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Remove a watermark from an item\n\nEXAMPLES\n  $ box watermarking:remove folder 22222\n```\n\n_See code: [src/commands/watermarking/remove.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/watermarking/remove.js)_\n"
  },
  {
    "path": "docs/web-links.md",
    "content": "`box web-links`\n===============\n\nManage web links\n\n* [`box web-links:create URL`](#box-web-linkscreate-url)\n* [`box web-links:delete ID`](#box-web-linksdelete-id)\n* [`box web-links:get ID`](#box-web-linksget-id)\n* [`box web-links:move ID PARENTID`](#box-web-linksmove-id-parentid)\n* [`box web-links:update ID`](#box-web-linksupdate-id)\n\n## `box web-links:create URL`\n\nCreate a new web link\n\n```\nUSAGE\n  $ box web-links:create URL --parent-id <value> [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-d <value>] [-n\n    <value>]\n\nARGUMENTS\n  URL  The URL the web link points to. Must start with \"http://\" or \"https://\"\n\nFLAGS\n  -d, --description=<value>        Description of the web link\n  -h, --help                       Show CLI help\n  -n, --name=<value>               Name of the web link. Defaults to the URL if not set\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --parent-id=<value>          (required) ID of the folder to create the web link in\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Create a new web link\n\nEXAMPLES\n  $ box web-links:create http://example.com --parent-id 0\n```\n\n_See code: [src/commands/web-links/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/web-links/create.js)_\n\n## `box web-links:delete ID`\n\nDelete a web link\n\n```\nUSAGE\n  $ box web-links:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the web link to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a web link\n\nEXAMPLES\n  $ box web-links:delete 12345\n```\n\n_See code: [src/commands/web-links/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/web-links/delete.js)_\n\n## `box web-links:get ID`\n\nGet information about a web link\n\n```\nUSAGE\n  $ box web-links:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the web link to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a web link\n\nEXAMPLES\n  $ box web-links:get 12345\n```\n\n_See code: [src/commands/web-links/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/web-links/get.js)_\n\n## `box web-links:move ID PARENTID`\n\nMove a web link\n\n```\nUSAGE\n  $ box web-links:move ID PARENTID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s |\n    --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID        ID of the web link to move\n  PARENTID  ID of the parent folder to move the web link into\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Move a web link\n\nEXAMPLES\n  $ box web-links:move 12345 22222\n```\n\n_See code: [src/commands/web-links/move.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/web-links/move.js)_\n\n## `box web-links:update ID`\n\nUpdate a web link\n\n```\nUSAGE\n  $ box web-links:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-d <value>] [-n <value>] [-u <value>]\n\nARGUMENTS\n  ID  ID of the web link to update\n\nFLAGS\n  -d, --description=<value>        Description of the web link\n  -h, --help                       Show CLI help\n  -n, --name=<value>               Name of the web link\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -u, --url=<value>                The URL the web link points to. Must start with \"http://\" or \"https://\"\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Update a web link\n\nEXAMPLES\n  $ box web-links:update 12345 --name \"Example Site\"\n```\n\n_See code: [src/commands/web-links/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/web-links/update.js)_\n"
  },
  {
    "path": "docs/webhooks.md",
    "content": "`box webhooks`\n==============\n\nList all webhooks\n\n* [`box webhooks`](#box-webhooks)\n* [`box webhooks:create TARGETTYPE TARGETID`](#box-webhookscreate-targettype-targetid)\n* [`box webhooks:delete ID`](#box-webhooksdelete-id)\n* [`box webhooks:get ID`](#box-webhooksget-id)\n* [`box webhooks:list`](#box-webhookslist)\n* [`box webhooks:update ID`](#box-webhooksupdate-id)\n\n## `box webhooks`\n\nList all webhooks\n\n```\nUSAGE\n  $ box webhooks [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all webhooks\n\nALIASES\n  $ box webhooks:list\n\nEXAMPLES\n  $ box webhooks\n```\n\n_See code: [src/commands/webhooks/index.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/webhooks/index.js)_\n\n## `box webhooks:create TARGETTYPE TARGETID`\n\nCreate a new webhook\n\n```\nUSAGE\n  $ box webhooks:create TARGETTYPE TARGETID -T <value> -a <value> [-t <value>] [--as-user <value>] [--no-color]\n    [--json | --csv] [-s | --save-to-file-path <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y]\n    [-q] [--id-only]\n\nARGUMENTS\n  TARGETTYPE  (file|folder) Type of Box item to create a webhook on\n  TARGETID    ID of the Box item to create a webhook on\n\nFLAGS\n  -T, --triggers=<value>           (required) Triggers for webhook as a comma separated list, e.g.\n                                   FILE.DELETED,FILE.PREVIEWED\n  -a, --address=<value>            (required) URL for your webhook handler\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --id-only                    Return only an ID to output from this command\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Create a new webhook\n\nEXAMPLES\n  $ box webhooks:create folder 22222 --triggers FILE.DELETED --address https://example.com/webhook/deletion\n```\n\n_See code: [src/commands/webhooks/create.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/webhooks/create.js)_\n\n## `box webhooks:delete ID`\n\nDelete a webhook\n\n```\nUSAGE\n  $ box webhooks:delete ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the webhook to delete\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Delete a webhook\n\nEXAMPLES\n  $ box webhooks:delete 12345\n```\n\n_See code: [src/commands/webhooks/delete.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/webhooks/delete.js)_\n\n## `box webhooks:get ID`\n\nGet information about a webhook\n\n```\nUSAGE\n  $ box webhooks:get ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q]\n\nARGUMENTS\n  ID  ID of the webhook to get\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Get information about a webhook\n\nEXAMPLES\n  $ box webhooks:get 12345\n```\n\n_See code: [src/commands/webhooks/get.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/webhooks/get.js)_\n\n## `box webhooks:list`\n\nList all webhooks\n\n```\nUSAGE\n  $ box webhooks:list [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [--max-items <value>]\n\nFLAGS\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --max-items=<value>          A value that indicates the maximum number of results to return. This only specifies a\n                                   maximum boundary and will not guarantee the minimum number of results returned. When\n                                   the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will\n                                   be made.\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  List all webhooks\n\nALIASES\n  $ box webhooks:list\n\nEXAMPLES\n  $ box webhooks\n```\n\n## `box webhooks:update ID`\n\nUpdate a webhook\n\n```\nUSAGE\n  $ box webhooks:update ID [-t <value>] [--as-user <value>] [--no-color] [--json | --csv] [-s | --save-to-file-path\n    <value>] [--fields <value>] [--bulk-file-path <value>] [-h] [-v] [-y] [-q] [-T <value>] [-a <value>]\n\nARGUMENTS\n  ID  ID of the webhook to update\n\nFLAGS\n  -T, --triggers=<value>           Triggers for webhook, enter as comma separated list. For example:\n                                   FILE.DELETED,FILE.PREVIEWED\n  -a, --address=<value>            URL for your webhook handler\n  -h, --help                       Show CLI help\n  -q, --quiet                      Suppress any non-error output to stderr\n  -s, --save                       Save report to default reports folder on disk\n  -t, --token=<value>              Provide a token to perform this call\n  -v, --verbose                    Show verbose output, which can be helpful for debugging\n  -y, --yes                        Automatically respond yes to all confirmation prompts\n      --as-user=<value>            Provide an ID for a user\n      --bulk-file-path=<value>     File path to bulk .csv or .json objects\n      --csv                        Output formatted CSV\n      --fields=<value>             Comma separated list of fields to show\n      --json                       Output formatted JSON\n      --no-color                   Turn off colors for logging\n      --save-to-file-path=<value>  Override default file path to save report\n\nDESCRIPTION\n  Update a webhook\n\nEXAMPLES\n  $ box webhooks:update 12345 --triggers FILE.DELETED,FOLDER.DELETED\n```\n\n_See code: [src/commands/webhooks/update.js](https://github.com/box/boxcli/blob/v4.8.0/src/commands/webhooks/update.js)_\n"
  },
  {
    "path": "eslint.config.cjs",
    "content": "// eslint.config.js\nconst js = require('@eslint/js');\nconst pluginPromise = require('eslint-plugin-promise');\nconst pluginUnicorn = require('eslint-plugin-unicorn');\nconst pluginN = require('eslint-plugin-n');\nconst prettier = require('eslint-config-prettier');\nconst pluginMocha = require('eslint-plugin-mocha');\nconst globals = require('globals');\n\nmodule.exports = [\n\tjs.configs.recommended,\n\t{\n\t\tfiles: ['**/*.js'],\n\t\tignores: ['dist/**', 'tmp/**', 'coverage/**'],\n\t\tlanguageOptions: {\n\t\t\tecmaVersion: 2022,\n\t\t\tsourceType: 'commonjs',\n\t\t\tglobals: {\n\t\t\t\t// Node.js globals\n\t\t\t\t...globals.node,\n\t\t\t\t...globals.mocha,\n\t\t\t},\n\t\t},\n\t\tplugins: {\n\t\t\tpromise: pluginPromise,\n\t\t\tunicorn: pluginUnicorn,\n\t\t\tn: pluginN,\n\t\t\tmocha: pluginMocha,\n\t\t},\n\t\trules: {\n\t\t\t...pluginPromise.configs.recommended.rules,\n\t\t\t...pluginN.configs.recommended.rules,\n\t\t\t...pluginUnicorn.configs.recommended.rules,\n\t\t\t...pluginMocha.configs.recommended.rules,\n\t\t\t// Give warnings for rules should fix in the future\n\t\t\t'no-prototype-builtins': 'warn',\n\t\t\t// Disable rules that don't fit this CommonJS project\n\t\t\t'unicorn/prefer-module': 'off',\n\t\t\t'unicorn/prevent-abbreviations': 'off',\n\t\t\t'unicorn/no-null': 'off',\n\t\t\t'unicorn/prefer-spread': 'warn',\n\t\t\t'unicorn/no-array-reduce': 'warn',\n\t\t\t'unicorn/no-await-expression-member': 'warn',\n\t\t\t'unicorn/prefer-structured-clone': 'warn',\n\t\t\t// Disable Mocha rule that doesn't fit existing test patterns\n\t\t\t'mocha/no-setup-in-describe': 'off',\n\t\t},\n\t},\n\tprettier,\n];\n"
  },
  {
    "path": "examples/Inactive Users Report/InactiveUsers.csv",
    "content": "\"name\",\"email\",\"id\",\"role\",\"status\",\"space_used\"\r\n\"Managed User 1\",\"mgrytsai+ManagedUser1@boxdemo.com\",\"20144610428\",\"user\",\"active\",\"0\"\n\"Managed User 2\",\"mgrytsai+ManagedUser2@boxdemo.com\",\"20145312516\",\"user\",\"active\",\"0\"\n\"Managed User 3\",\"mgrytsai+ManagedUser3@boxdemo.com\",\"20145270033\",\"user\",\"active\",\"0\"\n\"Managed User 4\",\"mgrytsai+ManagedUser4@boxdemo.com\",\"20145331112\",\"user\",\"active\",\"0\"\n\"Managed User 5\",\"mgrytsai+ManagedUser5@boxdemo.com\",\"20145104992\",\"user\",\"active\",\"0\"\n"
  },
  {
    "path": "examples/Inactive Users Report/Inactive_Users_Report.ps1",
    "content": "#APP SETUP\n#README: This powershell script will create list of users which inactive for more than a specified number of days.\n\n#APPLICATION ACCESS LEVEL (FOR JWT APPS): App + Enterprise Access\n\n########################################################################################\n###   SCRIPT CONFIG - MODIFY THESE FOR YOUR ENVIRONMENT   ##############################\n########################################################################################\n\n    $ReportName = \"InactiveUsers\"\n    $ReportOutputFile = $ReportName + \".csv\"\n\n    # The number of days to look back for inactive users.\n    $daysInactive = -1\n\n    # Filter events by type.\n    $eventType = \"LOGIN,UPLOAD,COPY,MOVE,PREVIEW,DOWNLOAD,EDIT,DELETE,UNDELETE,LOCK,UNLOCK,NEW_USER\"\n\n########################################################################################\n###   SCRIPT BUSINESS LOGIC - MODIFY ANYTHING BELOW THIS POINT   #######################\n########################################################################################\n\n# Get current script file name\nFunction Get-Script-Name() {\n    $filename = $MyInvocation.ScriptName | Split-Path -Leaf\n    if ($filename -match \".\") {\n        $filename = $filename.Substring(0, $filename.LastIndexOf(\".\"))\n    }\n\n    return $filename\n}\n\n# Function to write to logs\nFunction Write-Log { param ([string]$message, [string]$errorMessage = $null, [Exception]$exception = $null, [string]$output = $false, [string]$color = \"Green\")\n\n    # Define log level - Can be \"errors\" or \"all\"\n    $logLevel = \"all\"\n\n    # Create logs directory if it doesn't exist\n    if (-not (Test-Path \".\\logs\")) {\n        New-Item -Path . -Name \"logs\" -ItemType 'directory' > $null\n    }\n\n    $dateTime = Get-Date\n\n    # Set log filename to the name of the script\n    $logFilename = Get-Script-Name\n    $debugErrorFile = \".\\logs\\\" + $logFilename + \"_errors.txt\"\n    $debugAllFile = \".\\logs\\\" + $logFilename + \"_all.txt\"\n\n    if ($exception -or $errorMessage) {\n        $severity = \"ERROR\"\n    } else {\n        $severity = \"INFO\"\n    }\n\n    if ($exception.Response) {\n        $result = $exception.Response.GetResponseStream()\n        $reader = New-Object System.IO.StreamReader($result)\n        $reader.BaseStream.Position = 0\n        $reader.DiscardBufferedData()\n        $responseBody = $reader.ReadToEnd();\n    }\n\n    $logMessage = ($severity + \"`t\")\n    $logMessage += ($dateTime)\n    $logMessage += (\"`t\" + $message + \"`t\")\n\n    if ($exception) {\n        $logMessage += ($exception.Message + \"`t\")\n    }\n\n    if ($errorMessage) {\n        $logMessage += ($errorMessage + \"`t\")\n    }\n\n    if ($responseBody) {\n        $logMessage += (\"Box responded with: \" + $responseBody + \"`t\")\n    }\n\n    if ($output -eq \"true\") {\n        Write-Host $message -ForegroundColor $color\n    }\n\n    if ($logLevel -eq \"all\") {\n        $logMessage | Add-Content $debugAllFile\n\n        if ($severity -eq \"ERROR\") {\n            $logMessage | Add-Content $debugErrorFile\n        }\n    } else {\n        if ($severity -eq \"ERROR\") {\n            $logMessage | Add-Content $debugErrorFile\n        }\n    }\n}\n\n# This class is used for setting/restoring analytics client header when running this script\nclass AnalyticsClientManager {\n    [string]$TemporaryAnalyticsClientName\n    [string]$OriginalAnalyticsClientName\n    [bool]$IsOriginalAnalyticsClientEnabled\n\n    AnalyticsClientManager([string]$temporaryAnalyticsClientName) {\n        $this.TemporaryAnalyticsClientName = \"box_sample_scripts $($temporaryAnalyticsClientName)\"\n    }\n\n    [bool] IsAnalyticsClientSupported() {\n        return \"$(box  configure:settings --help)\" -like \"*--analytics-client-name*--json*\"\n    }\n\n    [void] StoreOriginalSettings() {\n        $SettingsContent = \"$(box configure:settings --json)\" | ConvertFrom-Json\n\n        $this.OriginalAnalyticsClientName = $SettingsContent.AnalyticsClient.Name\n        if (!$this.OriginalAnalyticsClientName) {\n            $this.OriginalAnalyticsClientName = \"cli\"\n        }\n\n        if($SettingsContent.EnableanalyticsClient) {\n            $this.IsOriginalAnalyticsClientEnabled = $true\n        } else {\n            $this.IsOriginalAnalyticsClientEnabled = $false\n        }\n\n        Write-Log \"Stored original analytics client settings, name: $($this.OriginalAnalyticsClientName), enabled: $($this.IsOriginalAnalyticsClientEnabled).\" -output false\n    }\n\n    [void] RestoreOriginalSettings() {\n        if ($this.IsOriginalAnalyticsClientEnabled) {\n            $RestoreAnalyticsClientEnablementState = \"--enable-analytics-client\"\n        } else {\n            $RestoreAnalyticsClientEnablementState = \"--no-enable-analytics-client\"\n        }\n\n        \"$(box configure:settings $RestoreAnalyticsClientEnablementState --analytics-client-name=$($this.OriginalAnalyticsClientName))\"\n        Write-Log \"Restored original analytics client settings, name: $($this.OriginalAnalyticsClientName), enabled: $($this.IsOriginalAnalyticsClientEnabled).\" -output false\n    }\n\n    [void] SetScriptAnalyticsClient() {\n        if ($this.IsAnalyticsClientSupported()) {\n            $this.StoreOriginalSettings()\n\n            \"$(box configure:settings --enable-analytics-client --analytics-client-name=$($this.TemporaryAnalyticsClientName))\"\n            Write-Log \"Set temporarily analytics client settings, name: $($this.TemporaryAnalyticsClientName), enabled: true.\" -output false\n        }\n    }\n\n    [void] UnsetScriptAnalyticsClients() {\n        if ($this.IsAnalyticsClientSupported()) {\n            $this.RestoreOriginalSettings()\n        }\n    }\n}\n\n# Generate inactive usres report\nFunction Start-Inactive-Users-Report-Script {\n    # Read the number of days to look back from the user\n    while ($daysInactive -lt 0) {\n        $daysInactive = Read-Host \"Enter the number of days to look back for inactive users\"\n        if ($daysInactive -lt 0) {\n            Write-Log \"Invalid number of days. Please enter a number greater than 0.\" -output true -color Red\n        }\n    }\n    Write-Log \"Looking for users inactive for more than $daysInactive day$(If($daysInactive -gt 1) {\"s\"}).\" -output true\n\n    # Get the current list of users\n    try {\n        $usersObjResp = \"$(box users --fields='id,login,name,role,space_used,is_platform_access_only,status' --json 2>&1)\"\n        $usersObj = $usersObjResp | ConvertFrom-Json\n        if (($usersObj.Length -eq 0) -or ($usersObj.total_count -eq 0)) {\n            Write-Log \"No users found!\" -output true -color Red\n        } else {\n            Write-Log \"Found $($usersObj.Length) user$(If($usersObj.Length -gt 1) {\"s\"}).\" -output true\n        }\n    }\n    catch {\n        Write-Log \"Could not get user list\" -errorMessage $usersObjResp -output true -color Red\n        break\n    }\n\n    # Get the current list of events\n    try {\n        $userEventObjResp = \"$(box events --enterprise --limit=500 --created-after=-$($daysInactive)d --event-types=$eventType --fields='source,created_by,event_type' --json 2>&1)\"\n        $userEventObj = $userEventObjResp | ConvertFrom-Json\n        if (($userEventObj.Length -eq 0) -or ($userEventObj -eq 0)) {\n            Write-Log \"No event was found for last $daysInactive days!\" -output Yellow\n        } else {\n            Write-Log \"Found $($userEventObj.Length) event$(If($userEventObj.Length -gt 1) {\"s\"}) in last $daysInactive day$(If($daysInactive -gt 1) {\"s\"})\" -output true\n        }\n    }\n    catch {\n        Write-Log \"Could not get event list\" -errorMessage $userEventObjResp -output true -color Red\n        break\n    }\n\n    $totalUsers = $usersObj.Length\n    $totalAppUser = 0\n    $totalUserRole = 0\n    $totalAdminRole = 0\n    $totalUnknownRole = 0\n    $activeUsers = @{}\n\n    # Create a dictionary of user IDs and count for each role\n    ForEach($User in $usersObj) {\n        if ($User.is_platform_access_only -eq $true) {\n            $totalAppUser++\n        }\n        if (($User.role -eq \"admin\") -or ($User.role -eq \"coadmin\")) {\n            $totalAdminRole += 1\n        } elseif ($User.role -eq \"user\") {\n            $totalUserRole += 1\n            if ($User.is_platform_access_only -eq $false) {\n                $activeUsers.Add($User.id, $false)\n            }\n        } else {\n            $totalUnknownRole += 1\n        }\n    }\n    $totalRegularUser = $totalUsers - $totalAppUser\n    $totalUserToCheck = $activeUsers.Count\n    Write-Log \"Enterprise has: $($totalAppUser) App user$(If($totalAppUser -gt 1) {\"s\"}), $($totalRegularUser) regular user$(If($totalRegularUser -gt 1) {\"s\"}). With $($totalAdminRole) admin role$(If($totalAdminRole -gt 1) {\"s\"}), $($totalUserRole) user role$(If($totalUserRole -gt 1) {\"s\"}).\" -output true\n    Write-Log \"Need to check $($totalUserToCheck) user$(If($totalUserToCheck -gt 1) {\"s\"}) (regular user, with user role) for inactive.\" -output true\n\n    # Perform the check\n    ForEach($Event in $userEventObj) {\n        # Check if user have just created\n        if ($Event.event_type -eq \"NEW_USER\") {\n            if ($activeUsers.ContainsKey($Event.source.id)) {\n                $activeUsers[$Event.source.id] = $true\n            }\n        }\n\n        # Mark user as active if they have event recently\n        if ($activeUsers.ContainsKey($Event.created_by.id)) {\n            $activeUsers[$Event.created_by.id] = $true\n        }\n    }\n\n    $totalInactiveUser = 0\n\n    # Write the output to a file\n    New-Item $ReportOutputFile -Value \"`\"name`\",`\"email`\",`\"id`\",`\"role`\",`\"status`\",`\"space_used`\"`r`n\" -ItemType File -Force > $null\n    ForEach($User in $usersObj) {\n        if ($activeUsers.ContainsKey($User.id) -and $activeUsers[$User.id] -eq $false) {\n            $totalInactiveUser += 1\n            Add-Content -Path $ReportOutputFile -Value \"`\"$($User.name)`\",`\"$($User.login)`\",`\"$($User.id)`\",`\"$($User.role)`\",`\"$($User.status)`\",`\"$($User.space_used)`\"\"\n        }\n    }\n\n    Write-Log \"Found $($totalInactiveUser) user$(If($totalInactiveUser -gt 1) {\"s\"}) inactive for more than $($daysInactive) day$(If($daysInactive -gt 1) {\"s\"}).\" -output true\n    Write-Log \"Report is available at $ReportOutputFile\" -output true\n}\n\n# Start function\nFunction Start-Script {\n    try {\n        $AnalyticsClientManager = [AnalyticsClientManager]::new($(Get-Script-Name).ToLower())\n        $AnalyticsClientManager.SetScriptAnalyticsClient()\n\n        Start-Inactive-Users-Report-Script\n    } finally {\n        $AnalyticsClientManager.UnsetScriptAnalyticsClients()\n    }\n}\n\n# Ensure console output is UTF-8 so non-ASCII characters from Box CLI render correctly\n[Console]::OutputEncoding = [System.Text.Encoding]::UTF8\nStart-Script\n"
  },
  {
    "path": "examples/Inactive Users Report/README.md",
    "content": "# Report inactive Users \n\n> Due to scale issue, CLI can't handle more than 1M events per run and as a run the Inactive Users Report will fail.\n\n**For detailed script overview, please follow [this guide][user-guide].**\n\nIdentifies inactive enterprise users by looking at user activity within a defined period of time. This script helps manage the number of seats within an enterprise and works in synergy with the deprovisioning script.\n\nThis script generates a `.csv` file with a list of users who has been inactive for a number of days. It performs the following steps:\n\n1. Looks for the users who have the role `user`.\n   > The script does not consider other roles, such as `AppUser`.\n\n2. Uses [Box Events][boxevents] to check if the user performed any actions   \n   for a specified number of days.\n   The default list of [event types][event-types] includes: `LOGIN`,`UPLOAD`,`COPY`,`MOVE`,`PREVIEW`,`DOWNLOAD`,`EDIT`,`DELETE`,`UNDELETE`,`LOCK`,`UNLOCK`, `NEW_USER`. You can modify this list in the script settings.\n3. Adds users who didn't perform any actions to a `.csv` file with\n   inactive users. You can use this file as input for other scripts, for example to [deprovision users][deprovisionscript].\n\n\n## Setup Pre-Requisites\n1. Clone this github repo or download files from the `/examples` directory\n   ```bash\n   git clone https://github.com/box/boxcli.git\n   ```\n2. Install PowerShell or .Net core.\n   > If you encounter issues make sure you install both dotnet core and PowerShell\n    1. For MacOS & Linux, Install the latest version of [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.2).\n    2. For Windows, Install the latest version of [dotnet core](https://dotnet.microsoft.com/download).\n    \n3. Test PowerShell by running the `pwsh` command in your terminal.\n    ```bash\n    pwsh\n    ```\n\n    ```\n    mikechen@mbp create-users-automation % pwsh\n    PowerShell 7.2.1\n    Copyright (c) Microsoft Corporation.\n\t\n    https://aka.ms/powershell\n    Type 'help' to get help.\n\t\n    PS /Users/mikechen>\n    ```\n4. Create an OAuth Application following the [CLI Setup Quick Start][oauth-guide].\n\n## 1. Script Parameters\n1. Set the [number of days][daysInactive-param] you want the script to scan for user events. If you   don't specify this value or leave the default, the script will prompt you to enter it.\n3. Optional: To change the report output file name, define the [ReportOutputFile][ReportName-param] parameter\n4. Optional: To change event types, define the list for [eventType][events-param] parameter.\n\n## 2. Run the script\n\nChange the directory to the folder containing the script. In this example, it is the `Inactive Users Report` folder.\n```\nrvb@lab:~/box-cli/examples/Inactive Users Report$ pwsh\nPowerShell 7.2.4\nCopyright (c) Microsoft Corporation.\n\nhttps://aka.ms/powershell\nType 'help' to get help.\n\nPS /home/rvb/box-cli/examples/Inactive Users Report>\n```\n\nRun the script:\n\n```bash\n./Inactive_Users_Report.ps1\n```\n\nWhen the script run is completed, you will see the following\noutput or a similar one.\n\n   ```bash\n    Looking for users inactive for more than 3 days.\n    Found 6 users.\n    Found 7 events in last 3 days\n    Enterprise has: 0 App user, 6 regular users. With 1 admin role, 5 user roles.\n    Need to check 5 users (regular user, with user role) for inactive.\n    Found 5 users inactive for more than 3 days.\n    Report is available at InactiveUsers.csv\n   ```\n\n## Logging\nLogs are stored in a `logs` folder located in the main folder. You have access to these log files:\n\n* `Inactive_Users_Report_all.txt` that contains all log entries.\n* `Inactive_Users_Report_errors.txt` that contains only errors.\n\n## Disclaimer\nThis project is a collection of open source examples and should not be treated as an officially supported product. Use at your own risk and as a source of example how to use Box CLI.\n\n[boxevents]:https://developer.box.com/reference/resources/event/\n[event-types]: https://developer.box.com/reference/resources/event/#param-event_type\n[oauth-guide]: https://developer.box.com/guides/cli/quick-start/\n[daysInactive-param]: /examples/Inactive%20Users%20Report/Inactive_Users_Report.ps1#L14\n[ReportName-param]: /examples/Inactive%20Users%20Report/Inactive_Users_Report.ps1#L11\n[events-param]: /examples/Inactive%20Users%20Report/Inactive_Users_Report.ps1#L17\n[deprovisionscript]: https://developer.box.com/guides/cli/scripts/deprovision-users/\n[user-guide]: https://developer.box.com/guides/cli/scripts/report-inactive-users/\n"
  },
  {
    "path": "examples/Integration Mappings/Integration-mappings.ps1",
    "content": "# This script can do one of the following things: \n# 1. Create a csv of all the current mappings between Box folders and Slack channels\n# 2. Create a mapping between a Box folder and a Slack channel based on a list in a csv file\n# 3. Update a mapping between a Box folder and a Slack channel based on a list in a csv file\n\n#APP SETUP\n#Oauth 2.0: User configured with CLI must be admin or co-admin\n#APPLICATION SCOPES: Read all files and folders stored in Box, & Manage Enterprise Settings\n\n#############################################################################\n\nparam (\n    # The action to perform. Can be \"EXTRACT\", \"CREATE\", or \"UPDATE\"\n    [string]$Action, \n\n    # The path to the csv file containing the mappings\n    [string]$MappingPath = \"./mapping.csv\"\n)\n\n#############################################################################\n\n# Get current script file name\nFunction Get-Script-Name()\n{\n    $filename = $MyInvocation.ScriptName | Split-Path -Leaf\n    if ($filename -match \".\")\n    {\n        $filename = $filename.Substring(0,$filename.LastIndexOf(\".\"))\n    }\n\n    return $filename\n}\n\n# Function to write to logs\nFunction Write-Log\n{\n    param ([string]$message, [string]$errorMessage = $null, [Exception]$exception = $null, [string]$output = $false, [string]$color = \"Green\")\n\n    # Define log level - Can be \"errors\" or \"all\"\n    $logLevel = \"all\"\n\n    # Create logs directory if it doesn't exist\n    if (-not(Test-Path \".\\logs\"))\n    {\n        New-Item -Path . -Name \"logs\" -ItemType 'directory' > $null\n    }\n\n    $dateTime = Get-Date\n\n    # Set log filename to the name of the script\n    $logFilename = Get-Script-Name\n    $debugErrorFile = \".\\logs\\\" + $logFilename + \"_errors.txt\"\n    $debugAllFile = \".\\logs\\\" + $logFilename + \"_all.txt\"\n\n    if ($exception -or $errorMessage)\n    {\n        $severity = \"ERROR\"\n    }\n    else\n    {\n        $severity = \"INFO\"\n    }\n\n    if ($exception.Response)\n    {\n        $result = $exception.Response.GetResponseStream()\n        $reader = New-Object System.IO.StreamReader($result)\n        $reader.BaseStream.Position = 0\n        $reader.DiscardBufferedData()\n        $responseBody = $reader.ReadToEnd();\n    }\n\n    $logMessage = ($severity + \"`t\")\n    $logMessage += ($dateTime)\n    $logMessage += (\"`t\" + $message + \"`t\")\n\n    if ($exception)\n    {\n        $logMessage += ($exception.Message + \"`t\")\n    }\n\n    if ($errorMessage)\n    {\n        $logMessage += ($errorMessage + \"`t\")\n    }\n\n    if ($responseBody)\n    {\n        $logMessage += (\"Box responded with: \" + $responseBody + \"`t\")\n    }\n\n    if ($output -eq \"true\")\n    {\n        Write-Host $message -ForegroundColor $color\n    }\n\n    if ($logLevel -eq \"all\")\n    {\n        $logMessage | Add-Content $debugAllFile\n\n        if ($severity -eq \"ERROR\")\n        {\n            $logMessage | Add-Content $debugErrorFile\n        }\n    }\n    else\n    {\n        if ($severity -eq \"ERROR\")\n        {\n            $logMessage | Add-Content $debugErrorFile\n        }\n    }\n}\n\n# This class is used for setting/restoring analytics client header when running this script\nclass AnalyticsClientManager\n{\n    [string]$TemporaryAnalyticsClientName\n    [string]$OriginalAnalyticsClientName\n    [bool]$IsOriginalAnalyticsClientEnabled\n\n    AnalyticsClientManager([string]$temporaryAnalyticsClientName)\n    {\n        $this.TemporaryAnalyticsClientName = \"box_sample_scripts $( $temporaryAnalyticsClientName )\"\n    }\n\n    [bool]\n    IsAnalyticsClientSupported()\n    {\n        return \"$( box configure:settings --help )\" -like \"*--analytics-client-name*--json*\"\n    }\n\n    [void]\n    StoreOriginalSettings()\n    {\n        $SettingsContent = \"$( box configure:settings --json )\" | ConvertFrom-Json\n\n        $this.OriginalAnalyticsClientName = $SettingsContent.AnalyticsClient.Name\n        if (!$this.OriginalAnalyticsClientName)\n        {\n            $this.OriginalAnalyticsClientName = \"cli\"\n        }\n\n        if ($SettingsContent.EnableanalyticsClient)\n        {\n            $this.IsOriginalAnalyticsClientEnabled = $true\n        }\n        else\n        {\n            $this.IsOriginalAnalyticsClientEnabled = $false\n        }\n\n        Write-Log \"Stored original analytics client settings, name: $( $this.OriginalAnalyticsClientName ), enabled: $( $this.IsOriginalAnalyticsClientEnabled ).\" -output false\n    }\n\n    [void]\n    RestoreOriginalSettings()\n    {\n        if ($this.IsOriginalAnalyticsClientEnabled)\n        {\n            $RestoreAnalyticsClientEnablementState = \"--enable-analytics-client\"\n        }\n        else\n        {\n            $RestoreAnalyticsClientEnablementState = \"--no-enable-analytics-client\"\n        }\n\n        \"$( box configure:settings $RestoreAnalyticsClientEnablementState --analytics-client-name=$($this.OriginalAnalyticsClientName) )\"\n        Write-Log \"Restored original analytics client settings, name: $( $this.OriginalAnalyticsClientName ), enabled: $( $this.IsOriginalAnalyticsClientEnabled ).\" -output false\n    }\n\n    [void]\n    SetScriptAnalyticsClient()\n    {\n        if ( $this.IsAnalyticsClientSupported())\n        {\n            $this.StoreOriginalSettings()\n\n            \"$( box configure:settings --enable-analytics-client --analytics-client-name=$($this.TemporaryAnalyticsClientName) )\"\n            Write-Log \"Set temporarily analytics client settings, name: $( $this.TemporaryAnalyticsClientName ), enabled: true.\" -output false\n        }\n    }\n\n    [void]\n    UnsetScriptAnalyticsClients()\n    {\n        if ( $this.IsAnalyticsClientSupported())\n        {\n            $this.RestoreOriginalSettings()\n        }\n    }\n}\n\n#############################################################################\n\n# Check if any of the command-line arguments are missing\n# If so, prompt the user to enter them\nif (-not $Action) {\n     Write-Log \"Enter EXTRACT to grabbing current mappings, CREATE to create new mappings, or UPDATE to update existing mappings:\" -output true -color Yellow\n     $Action = Read-Host\n}\n\nFunction Start-Integrations-Mapping {\n\n    Write-Log \"Starting Process\" -output true -color Green\n\n    try {\n        #If a user inputs EXTRACT it will grab the current mappings and save them to a csv file\n        #The csv is called mapping.csv by default and is saved in the same directory as the script\n        If ($Action -eq \"EXTRACT\") {\n            Write-Log \"Extracting current mappings\" -output true -color Green\n            if (Test-Path $MappingPath) {\n                Write-Log \"Removing old $($MappingPath) file\" -output true -color Green\n                Remove-Item -Path $MappingPath -Force\n                Write-Log \"File $($MappingPath) removed\" -output true -color Green\n            }\n            Write-Log \"Pulling current mappings\" -output true -color Green\n            $ExtractionResp = (box integration-mappings:slack:list --fields='id,box_item.id,partner_item.id' --csv --save-to-file-path=$MappingPath 2>&1)\n            Write-Log \"Importing csv\" -output true -color Green\n            # Import the CSV file\n            $data = Import-Csv -Path $MappingPath\n            Write-Log \"Renaming columns\" -output true -color Green\n            # Select the desired columns and rename them\n            $data = $data | Select-Object -Property \"id\", \"box_item.id\", \"partner_item.id\" |\n                    Select-Object -Property @{Name = \"Id\"; Expression = {$_. \"id\"}},\n                                            @{Name = \"BoxItemId\"; Expression = {$_. \"box_item.id\"}}, \n                                            @{Name = \"PartnerItemId\"; Expression = {$_. \"partner_item.id\"}}\n            Write-Log \"Saving new csv file to edit\" -output true -color Green\n            # Overwrite the original CSV file\n            $data | Export-Csv -Path $MappingPath -NoTypeInformation\n\n            Write-Log \"Extraction $($ExtractionResp | Out-String)\" -output true -color Green\n        \n        }\n        # If a user inputs CREATE it will create new mappings based on the csv file located by default at ./mapping.csv\n        # You can use the mapping_create_example.csv file as a template\n        # You cannot create new mappings for channels that already have mappings, instead you must update them using the UPDATE option\n        # When creating mappings for new channels, you must input a box folder id, slack channel id and slack org id for each row.\n        elseif ($Action -eq \"CREATE\") {\n            Write-Log \"Creating new mappings\" -output true -color Green\n            $EntriesResp = (box integration-mappings:slack:create --bulk-file-path=$MappingPath --json 2>&1)\n            # If the response contains the word failed, it probably means the channel already has a mapping or you are missing persmissons\n            if($EntriesResp | Select-String -Pattern 'failed!' -CaseSensitive -SimpleMatch) {\n                Write-Log \"Could not create mappings. See log for details.\" -errorMessage $EntriesResp -output true -color Red \n            } else {\n                Write-Log \"Output $($EntriesResp | Out-String)\" -output true -color Green\n                continue\n            }\n        }\n        # If a user inputs UPDATE it will update the new mappings from the csv file\n        # You can use the mapping_update_example.csv file as a template\n        elseif ($Action -eq \"UPDATE\") {\n            Write-Log \"Updating mappings\" -output true -color Green\n            $EntriesResp = (box integration-mappings:slack:update --bulk-file-path=$MappingPath --json 2>&1)\n            # If the response contains the word failed, it probably means the service account needs to be collabed into the folder(s)\n            if($EntriesResp | Select-String -Pattern 'failed!' -CaseSensitive -SimpleMatch) {\n                Write-Log \"Could not update mappings. See log for details.\" -errorMessage $EntriesResp -output true -color Red \n            } else {\n                Write-Log \"Output $($EntriesResp | Out-String)\" -output true -color Green\n                continue\n            }\n        }\n        else {\n            Write-Log \"Invalid option selected\" -output true -color Red\n            break\n        }\n    }\n    catch {\n        Write-Log \"Could not apply or extract mappings. See error log for details.\" -errorMessage $EntriesResp -output True -color Red\n        break\n    }\n}\n\n\n# Start function\nFunction Start-Script {\n    try {\n        $AnalyticsClientManager = [AnalyticsClientManager]::new($( Get-Script-Name ).ToLower())\n        $AnalyticsClientManager.SetScriptAnalyticsClient()\n\n        Start-Integrations-Mapping  # Start the script\n    }\n    finally {\n        $AnalyticsClientManager.UnsetScriptAnalyticsClients()\n    }\n}\n\n# Ensure console output is UTF-8 so non-ASCII characters from Box CLI render correctly\n[Console]::OutputEncoding = [System.Text.Encoding]::UTF8\nStart-Script\n"
  },
  {
    "path": "examples/Integration Mappings/README.md",
    "content": "# Integration Mappings (Slack)\n\nThis script helps manage the folder mappings between Slack and Box if using Box as the content store for Slack. It creates a list of current Slack channel and Box folder mappings and can create or update mappings based on input csv. This script will maintain all permissons. \n\nFor details, checkout the [Medium blog](https://medium.com/box-developer-blog/new-box-cli-automation-template-to-manage-slack-integration-folder-mappings-a174f9985768).\n\n## Setup Pre-Requisites\n1. Clone this github repo or download files from the `/examples` directory\n   ```bash\n   git clone https://github.com/box/boxcli.git\n   ```\n2. Install PowerShell or .Net core.\n   > If you encounter issues make sure you install both dotnet core and PowerShell\n\t1. For MacOS & Linux, Install the latest version of [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.2).\n\t2. For Windows, Install the latest version of [dotnet core](https://dotnet.microsoft.com/download).\n\n3. Test PowerShell by running the `pwsh` command in your terminal.\n    ```bash\n    pwsh\n    ```\n\n    ```\n    mikechen@mbp Integration Mappings % pwsh\n    PowerShell 7.2.1\n    Copyright (c) Microsoft Corporation.\n\t\n    https://aka.ms/powershell\n    Type 'help' to get help.\n\t\n    PS /Users/mikechen>\n    ```\n4. Configure and install the Box CLI using the OAuth [CLI Setup Quick Start][oauth-guide]. Make sure the user you use is an admin or co-admin.\n5. Configure and [install Box for Slack][install-slack] in the relevant Slack workspaces and orgs\n6. Box as the [content layer for Slack][content-layer] in enabled\n\n## Run the script\n\nChange the directory to the folder containing the script. In this example, it is the `Integration Mappings` folder.\n```pwsh\nrvb@lab:~/box-cli/examples/Integration Mappings$ pwsh\nPowerShell 7.2.4\nCopyright (c) Microsoft Corporation.\n\nhttps://aka.ms/powershell\nType 'help' to get help.\n\nPS /home/rvb/box-cli/examples/Integration Mappings>\n```\n\nRun the script with EXTRACT to extract current mappings:\n```pwsh\n./integration-mappings.ps1 -Action EXTRACT\n```\n\nor\n\nRun the script with UPDATE to update current mappings:\n```pwsh\n./integration-mappings.ps1 -Action UPDATE\n```\n\nor\n\nRun the script with CREATE to create new mappings:\n```pwsh\n./integration-mappings.ps1 -Action CREATE -MappingPath ./mapping_create_example.csv\n```\n\nBy default, the csv file will save to and load from ./mappings.csv. If you wish to change this location, you can pass in a new path like so:\n```pwsh\n./integration-mappings.ps1 -Action EXTRACT -MappingPath ./mappings_new_location.csv\n```\n\nIf you don't specify parameters, the script will prompt you to enter them.\n\nWhen the script run is completed, you will see the following\noutput or a similar one.\n\nWhen creating a mapping on a new channel, you must input a Box folder id, Slack channel id and Slack org id. You may use a Slack workspace ID in lieu of the org id. In that case, you would replace the csv column header `SlackOrgId` with `SlackWorkspaceId`.\n\n```\nStarting Process\nApplying new mappings\nOutput [...]\nAll bulk input entries processed successfully.\n```\n\n## Logging\nLogs are stored in a `logs` folder located in the main folder. You have access to these log files:\n\n* `Integration-mappings_all.txt` that contains all log entries.\n* `Integration-mappings_errors.txt` that contains only errors.\n\n## Disclaimer\nThis project is a collection of open source examples and should not be treated as an officially supported product. Use at your own risk and as a source of example how to use Box CLI.\n\n[oauth-guide]: https://developer.box.com/guides/cli/quick-start/\n[install-slack]: https://support.box.com/hc/en-us/articles/360044195313-Installing-and-Using-the-Box-for-Slack-Integration\n[content-layer]: https://support.box.com/hc/en-us/articles/4415585987859-Box-as-the-Content-Layer-for-Slack\n"
  },
  {
    "path": "examples/Integration Mappings/mapping_create_example.csv",
    "content": "\"BoxItemId\",\"ChannelId\",\"SlackOrgId\"\n\"123456789\",\"ABC123456\",\"XYZ12345678\""
  },
  {
    "path": "examples/Integration Mappings/mapping_update_example.csv",
    "content": "\"Id\",\"BoxItemId\",\"PartnerItemId\"\n\"12345\",\"123456789\",\"ABC12345678\""
  },
  {
    "path": "examples/Mass Groups & Collaborations Update/Collaborations_Creation.csv",
    "content": "GroupName,FolderId,CollaborationRole\nGroup 1,1111111,editor\nGroup 2,1111111,viewer_uploader\nGroup 2,2222222,viewer\nGroup 3,1111111,viewer_uploader\nGroup 3,3333333,editor\nGroup 3,4444444,editor\n"
  },
  {
    "path": "examples/Mass Groups & Collaborations Update/Mass_Groups_Collabs_Update.ps1",
    "content": "#APP SETUP\n#README: This powershell script will use the Box CLI to creates or updates groups with the given users and creates collaborations for groups.\n\n#APPLICATION ACCESS LEVEL (FOR JWT APPS): App + Enterprise Access\n#APPLICATION SCOPES: Manage Enterprise Properties, Manage Users, Manage Groups\n\n########################################################################################\n\nparam (\n    [switch]$SkipGroupsUpdate = $false, # if enabled, then will skip groups update\n    [switch]$SkipCollabsCreation = $false, # if enabled, then will skip collaborations creation\n    [switch]$UpdateExistingCollabs = $false # if enabled, then existing collaborations will be updated with new the role\n)\n\n########################################################################################\n###   SCRIPT CONFIG - MODIFY THESE FOR YOUR ENVIRONMENT   ##############################\n########################################################################################\n\n# Set user group addition CSV path\n$UserGroupAdditionPath = \"./User_Group_Addition.csv\"\n\n# Set collaborations creation CSV path\n$CollaborationsCreationPath = \"./Collaborations_Creation.csv\"\n\n# Default collaboration role, used when it's not set in CSV file\n$DefaultCollaborationRole = \"editor\"\n\n# Name of column names in CSV files\n$GroupNameColumnName = \"GroupName\"   # group name column name of csv input\n$UserEmailColumnName = \"UserEmail\" # user email column name of csv input\n$FolderIdColumnName = \"FolderId\" # folder id column name of csv input\n$CollaborationRoleColumnName = \"CollaborationRole\" # role column name of csv input\n\n# List of available collaboration roles\n$AvailableCollaborationRoles = @(\"editor\", \"viewer\", \"previewer\", \"uploader\", \"previewer_uploader\", \"viewer_uploader\", \"co-owner\")\n\n########################################################################################\n###   SCRIPT BUSINESS LOGIC - MODIFY ANYTHING BELOW THIS POINT   #######################\n########################################################################################\n\n$script:GroupsHashtable = @{}\n$script:UsersHashtable = @{}\n\n# Get current script file name\nFunction Get-Script-Name() {\n    $filename = $MyInvocation.ScriptName | Split-Path -Leaf\n    if ($filename -match \".\") {\n        $filename = $filename.Substring(0, $filename.LastIndexOf(\".\"))\n    }\n\n    return $filename\n}\n\n# Function to write to logs\nFunction Write-Log { param ([string]$message, [string]$errorMessage = $null, [Exception]$exception = $null, [string]$output = $false, [string]$color = \"Green\")\n\n    # Define log level - Can be \"errors\" or \"all\"\n    $logLevel = \"all\"\n\n    # Create logs directory if it doesn't exist\n    if (-not (Test-Path \".\\logs\")) {\n        New-Item -Path . -Name \"logs\" -ItemType 'directory' > $null\n    }\n\n    $dateTime = Get-Date\n\n    # Set log filename to the name of the script\n    $logFilename = Get-Script-Name\n    $debugErrorFile = \".\\logs\\\" + $logFilename + \"_errors.txt\"\n    $debugAllFile = \".\\logs\\\" + $logFilename + \"_all.txt\"\n\n    if ($exception -or $errorMessage) {\n        $severity = \"ERROR\"\n    } else {\n        $severity = \"INFO\"\n    }\n\n    if ($exception.Response) {\n        $result = $exception.Response.GetResponseStream()\n        $reader = New-Object System.IO.StreamReader($result)\n        $reader.BaseStream.Position = 0\n        $reader.DiscardBufferedData()\n        $responseBody = $reader.ReadToEnd();\n    }\n\n    $logMessage = ($severity + \"`t\")\n    $logMessage += ($dateTime)\n    $logMessage += (\"`t\" + $message + \"`t\")\n\n    if ($exception) {\n        $logMessage += ($exception.Message + \"`t\")\n    }\n\n    if ($errorMessage) {\n        $logMessage += ($errorMessage + \"`t\")\n    }\n\n    if ($responseBody) {\n        $logMessage += (\"Box responded with: \" + $responseBody + \"`t\")\n    }\n\n    if ($output -eq \"true\") {\n        Write-Host $message -ForegroundColor $color\n    }\n\n    if ($logLevel -eq \"all\") {\n        $logMessage | Add-Content $debugAllFile\n\n        if ($severity -eq \"ERROR\") {\n            $logMessage | Add-Content $debugErrorFile\n        }\n    } else {\n        if ($severity -eq \"ERROR\") {\n            $logMessage | Add-Content $debugErrorFile\n        }\n    }\n}\n\n# This class is used for setting/restoring analytics client header when running this script\nclass AnalyticsClientManager {\n    [string]$TemporaryAnalyticsClientName\n    [string]$OriginalAnalyticsClientName\n    [bool]$IsOriginalAnalyticsClientEnabled\n\n    AnalyticsClientManager([string]$temporaryAnalyticsClientName) {\n        $this.TemporaryAnalyticsClientName = \"box_sample_scripts $($temporaryAnalyticsClientName)\"\n    }\n\n    [bool] IsAnalyticsClientSupported() {\n        return \"$(box configure:settings --help)\" -like \"*--analytics-client-name*--json*\"\n    }\n\n    [void] StoreOriginalSettings() {\n        $SettingsContent = \"$(box configure:settings --json)\" | ConvertFrom-Json\n\n        $this.OriginalAnalyticsClientName = $SettingsContent.AnalyticsClient.Name\n        if (!$this.OriginalAnalyticsClientName) {\n            $this.OriginalAnalyticsClientName = \"cli\"\n        }\n\n        if($SettingsContent.EnableanalyticsClient) {\n            $this.IsOriginalAnalyticsClientEnabled = $true\n        } else {\n            $this.IsOriginalAnalyticsClientEnabled = $false\n        }\n\n        Write-Log \"Stored original analytics client settings, name: $($this.OriginalAnalyticsClientName), enabled: $($this.IsOriginalAnalyticsClientEnabled).\" -output false\n    }\n\n    [void] RestoreOriginalSettings() {\n        if ($this.IsOriginalAnalyticsClientEnabled) {\n            $RestoreAnalyticsClientEnablementState = \"--enable-analytics-client\"\n        } else {\n            $RestoreAnalyticsClientEnablementState = \"--no-enable-analytics-client\"\n        }\n\n        \"$(box configure:settings $RestoreAnalyticsClientEnablementState --analytics-client-name=$($this.OriginalAnalyticsClientName))\"\n        Write-Log \"Restored original analytics client settings, name: $($this.OriginalAnalyticsClientName), enabled: $($this.IsOriginalAnalyticsClientEnabled).\" -output false\n    }\n\n    [void] SetScriptAnalyticsClient() {\n        if ($this.IsAnalyticsClientSupported()) {\n            $this.StoreOriginalSettings()\n\n            \"$(box configure:settings --enable-analytics-client --analytics-client-name=$($this.TemporaryAnalyticsClientName))\"\n            Write-Log \"Set temporarily analytics client settings, name: $($this.TemporaryAnalyticsClientName), enabled: true.\" -output false\n        }\n    }\n\n    [void] UnsetScriptAnalyticsClients() {\n        if ($this.IsAnalyticsClientSupported()) {\n            $this.RestoreOriginalSettings()\n        }\n    }\n}\n\n########################################################################################\n###   Part 1) Update groups   ##########################################################\n########################################################################################\n\n# Function to create/update groups based on CSV file\nFunction Update-Groups {\n    Write-Log \"Start update groups...\" -output true\n\n    # Ensure that file exist\n    if (-not(Test-Path -Path $UserGroupAdditionPath -PathType Leaf)) {\n        Write-Log \"File '$UserGroupAdditionPath' doesn't exist. Skipping groups update.\" -errorMessage \"File not found.\"-output true -color Red\n        return\n    }\n\n    # Read the input CSV\n    try {\n        $AllGroupsInput = Import-Csv $UserGroupAdditionPath\n    } catch {\n        Write-Log \"Error reading '$UserGroupAdditionPath' CSV file. Skipping groups update.\" -exception $_.Exception -output true -color Red\n        return\n    }\n\n    # Check if there is any entry in the input file\n    if (!$($($AllGroupsInput | Measure-Object).Count -gt 0)) {\n        Write-Log \"No groups to act upon. Skipping groups update.\" -output true -color Yellow\n        return\n    }\n\n    # Check if the input file has the correct format\n    $csvColumns = $AllGroupsInput | Get-Member -memberType 'NoteProperty' | Select-Object -ExpandProperty 'Name'\n    if (-not (($csvColumns -contains $GroupNameColumnName) -and ($csvColumns -contains $UserEmailColumnName))) {\n        Write-Log \"Input file '$UserGroupAdditionPath' requires '$GroupNameColumnName' and '$UserEmailColumnName' columns. Skipping groups update.\" -errorMessage \"Invalid input data.\" -output true -color Red\n        return;\n    }\n\n    # Hashtable where group's id is the key and array of user's ids is a value\n    # e.g.:\n    # $GroupsMembershipHashtable['group_id_1'] = @('user_id_1', 'user_id_2', 'user_id_3')\n    # $GroupsMembershipHashtable['group_id_2'] = @('user_id_2', 'user_id_4')\n    $GroupsMembershipHashtable = @{}\n\n    $currentRowIndex = 0\n    # Iterate through all groups from CSV input file\n    foreach($GroupInputEntry in $AllGroupsInput) {\n        # Rows of input data starts with 1\n        $currentRowIndex++\n\n        # Get the name of the group being processed in the current row\n        $CurrentGroupName = $GroupInputEntry.$GroupNameColumnName\n\n        # Ensure that it's not empty\n        if (!$CurrentGroupName) {\n            Write-Log \"'$GroupNameColumnName' column in row $currentRowIndex) contains invalid empty value. Skipping processing current row.\"  -errorMessage \"Invalid input data.\" -output true -color Red\n            continue\n        }\n\n        if (!$GroupsHashtable.ContainsKey($CurrentGroupName)) {\n            # If the group with given name doesn't exist, create it\n            try {\n                $CreatedGroupResp = \"$(box groups:create $CurrentGroupName --json 2>&1)\"\n                $CreatedGroup = $CreatedGroupResp | ConvertFrom-Json\n\n                # Add created group to the set of existing groups -> GroupsHashtable\n                $GroupsHashtable[$CreatedGroup.name] = $CreatedGroup.id\n\n                 # Create entry for created group with empty array set as value\n                $GroupsMembershipHashtable[$CreatedGroup.id] = @()\n\n                Write-Log \"Successfully created group '$CurrentGroupName' with ID $($CreatedGroup.id)\" -output true\n                Write-Log \"$CreatedGroupResp\"\n            } catch {\n                Write-Log \"Could not create a '$CurrentGroupName' group. See log for details. Skipping processing current row.\" -errorMessage $CreatedGroupResp -output true -color Red\n                continue\n            }\n        } else {\n            Write-Log \"Group '$CurrentGroupName' already exists.\" -output false\n        }\n\n        # Now we can fetch id of group from hashtable\n        $CurrentGroupID = $GroupsHashtable[$CurrentGroupName]\n\n        # If current processing ID of the group is not in GroupsMembershipHashtable, then fetch members of this group\n        if (!$GroupsMembershipHashtable.ContainsKey($CurrentGroupID)) {\n            try {\n                # Get members of the group\n                $GroupMembershipResp = \"$(box groups:memberships $CurrentGroupID --fields='user' --json 2>&1)\"\n                $GroupMembership = $GroupMembershipResp | ConvertFrom-Json\n\n                # Update hashtable GroupsMembershipHashtable by adding list of user's ids to particular group id\n                $GroupsMembershipHashtable.$CurrentGroupID = @()\n                $GroupMembership | ForEach-Object { $GroupsMembershipHashtable.$CurrentGroupID += $_.user.id }\n\n                Write-Log \"Successfully fetched the members of the group '$CurrentGroupName' (ID:$CurrentGroupID).\" -output true\n                Write-Log $GroupMembership\n            } catch {\n                Write-Log \"Could not fetch the members of the group '$CurrentGroupName' (ID:$CurrentGroupID). See log for details. Skipping processing current row.\" -errorMessage $GroupMembershipResp -output true -color Red\n                continue\n            }\n        }\n\n        # Get the user's email being processed in the current row\n        $CurrentUserEmail = $GroupInputEntry.$UserEmailColumnName\n\n        # Ensure that it's not empty\n        if (!$CurrentUserEmail) {\n            Write-Log \"'$UserEmailColumnName' column in row $currentRowIndex) contains invalid empty value. Skipping processing current row.\" -errorMessage \"Invalid input data.\" -output true -color Red\n            continue\n        }\n\n        # Ensure tha users exists in your enterprise\n        if (!$UsersHashtable.ContainsKey($CurrentUserEmail)) {\n            Write-Log \"Could not find user with email: '$CurrentUserEmail'. Skipping processing current row.\" -errorMessage \"User not found.\" -output true -color Red\n            continue\n        }\n\n        # Get user's Id from hashtable\n        $CurrentUserID = $UsersHashtable[$CurrentUserEmail]\n\n        # Add user to group only if it's not there already\n        if($GroupsMembershipHashtable[$CurrentGroupID].Contains($CurrentUserID)) {\n            Write-Log \"User '$CurrentUserEmail' (ID: $CurrentUserID) is already in group $CurrentGroupName' (ID:$CurrentGroupID)'. Skipping processing current row.\" -output true\n            continue\n        }\n        else {\n            try {\n                # Add user to group\n                $AddedGroupMembershipResp = \"$(box groups:memberships:add $CurrentUserID $CurrentGroupID --json 2>&1)\"\n                $AddedGroupMembership = $AddedGroupMembershipResp | ConvertFrom-Json\n\n                # Update membership hashtable by adding user id to the list of ids assigned to particular group\n                $GroupsMembershipHashtable.$CurrentGroupID += $AddedGroupMembership.user.id\n\n                Write-Log \"Successfully added user '$CurrentUserEmail' (ID: $CurrentUserID) to group '$CurrentGroupName' (ID:$CurrentGroupID).\" -output true\n                Write-Log $AddedGroupMembershipResp\n            } catch {\n                Write-Log \"Could not add user '$CurrentUserEmail' (ID: $CurrentUserID) to group '$CurrentGroupName' (ID:$CurrentGroupID). See log for details.\" -errorMessage $AddedGroupMembershipResp -output true -color Red\n                continue\n            }\n        }\n    }\n\n    Write-Log \"Finish update groups.\" -output true\n}\n\n########################################################################################\n###   Part 2) Update collaborations   ##################################################\n########################################################################################\n\n# Collaboration group class used to tracking collaborations locally\nclass CollaborationGroup {\n    [string]$CollaborationId\n    [string]$GroupId\n    [string]$Role\n\n    CollaborationGroup([System.Object]$collaborationItem) {\n        $this.CollaborationId = $collaborationItem.id\n        $this.GroupId = $collaborationItem.accessible_by.id\n        $this.Role = $collaborationItem.role.Replace(\" \",\"_\")\n    }\n\n    CollaborationGroup([string]$cId, [string]$gId, [string]$r) {\n        $this.CollaborationId = $cId\n        $this.GroupId = $gId\n        $this.Role = $r.Replace(\" \",\"_\")\n    }\n}\n\n# This class is used for convenient accessing/tracking collaborations assigned to folders\nclass FolderCollaborationStorage {\n    # Hashtable where folder's id is the key and array of CollaborationGroup is a value\n    $hashtable = @{}\n\n    [void] AddCollaborationGroupForFolder([CollaborationGroup]$entry, [string]$folderId) {\n        $this.hashtable.$folderId += $entry\n    }\n\n    [bool] ContainsFolderId([string]$folderId) {\n        return $this.hashtable.ContainsKey($folderId)\n    }\n\n    [void] AddFolderId([string]$folderId) {\n        if(!$this.hashtable.ContainsKey($folderId)) {\n            $this.hashtable.$folderId = @()\n        }\n    }\n\n    [CollaborationGroup] GetCollaborationGroup([string]$groupId, [string]$folderId) {\n         return $this.hashtable[$folderId] | Where-Object { $_.GroupId -eq $groupId } | Select-Object -First 1\n    }\n\n    [bool] ContainsCollaborationGroup([string]$groupId, [string]$folderId) {\n        return $null -ne $this.GetCollaborationGroup($groupId, $folderId)\n   }\n}\n\n# Function to create collaborations based on CSV file\nFunction Update-Collaborations {\n    Write-Log \"Start create collaborations...\" -output true\n\n    # Ensure that file exist\n    if (-not(Test-Path -Path $CollaborationsCreationPath -PathType Leaf)) {\n        Write-Log \"File '$CollaborationsCreationPath' doesn't exist. Skipping groups update.\" -errorMessage \"File not found.\"-output true -color Red\n        return\n    }\n\n    # Read the input CSV\n    try {\n        $AllCollaborationsInput = Import-Csv $CollaborationsCreationPath\n    } catch {\n        Write-Log \"Error reading '$CollaborationsCreationPath' CSV file. Skipping collaborations creation.\" -exception $_.Exception -output true -color Red\n        return\n    }\n\n    # Check if there are any group in the input\n    if (!$($($AllCollaborationsInput | Measure-Object).Count -gt 0)) {\n        Write-Log \"No collaborations to act upon. Skipping collaborations creation.\" -output true -color Yellow\n        return\n    }\n\n    # Check if input file has the correct format\n    $csvColumns = $AllCollaborationsInput | Get-Member -memberType 'NoteProperty' | Select-Object -ExpandProperty 'Name'\n    if (-not\n        (\n            ($csvColumns -contains $GroupNameColumnName) -and\n            ($csvColumns -contains $FolderIdColumnName) -and\n            ($csvColumns -contains $CollaborationRoleColumnName)\n        )\n    ) {\n        Write-Log \"Input file '$CollaborationsCreationPath' requires '$GroupNameColumnName', '$FolderIdColumnName' and '$CollaborationRoleColumnName' columns. Skipping collaborations creation.\" -errorMessage \"Invalid input data.\" -output true -color Red\n        return;\n    }\n\n    # Create a storage for collaborations for easier accessing necessary data\n    $FolderCollaborationStorage = [FolderCollaborationStorage]::new()\n\n    $currentRowIndex = 0\n    # Iterate through all entries from CSV input file\n    foreach($CollaborationInputEntry in $AllCollaborationsInput) {\n        # Rows of input data starts with 1\n        $currentRowIndex++\n\n        # Get the name of the group being processed in the current row\n        $CurrentGroupName = $CollaborationInputEntry.$GroupNameColumnName\n\n        # Ensure that it's not empty\n        if (!$CurrentGroupName) {\n            Write-Log \"'$GroupNameColumnName' column in row $currentRowIndex) contains invalid empty value. Skipping processing current row.\"  -errorMessage \"Invalid input data.\" -output true -color Red\n            continue\n        }\n\n        # Ensure that a group with that name exists, if not skip processing current row\n        if (!$GroupsHashtable.ContainsKey($CurrentGroupName)) {\n            Write-Log \"Group with name '$CurrentGroupName' doesn't exist. Skipping processing current row.\" -errorMessage \"Invalid group name.\" -output true -color Red\n            continue\n        }\n\n        # Get id of group from hashtable\n        $CurrentGroupID = $GroupsHashtable[$CurrentGroupName]\n\n        # Get the folderId being processed in the current row\n        $CurrentFolderID = $CollaborationInputEntry.$FolderIdColumnName\n\n        # Ensure that it's not empty\n        if (!$CurrentFolderID) {\n            Write-Log \"'$FolderIdColumnName' column in row $currentRowIndex) contains invalid empty value. Skipping processing current row.\" -errorMessage \"Invalid input data.\" -output true -color Red\n            continue\n        }\n\n        # Get the name of the collaboration role being processed in the current row\n        $CurrentCollaborationRole = $CollaborationInputEntry.$CollaborationRoleColumnName\n\n        if (!$CurrentCollaborationRole) {\n            # Use default collaboration role if it's empty\n            $CurrentCollaborationRole = $DefaultCollaborationRole\n        }\n\n        # Ensure that collaboration role is set to valid value\n        if (!$AvailableCollaborationRoles.Contains($CurrentCollaborationRole)) {\n            Write-Log \"'$CollaborationRoleColumnName' column in row $currentRowIndex) contains invalid value: '$CurrentCollaborationRole'. Please use one of these: '$($AvailableCollaborationRoles -join \", \")'. Skipping processing current row.\" -errorMessage \"Invalid input data.\" -output true -color Red\n            continue\n        }\n\n        # If current processing folderId is not in FolderCollaborationStorage, then fetch collaborations of this folder\n        if(!$FolderCollaborationStorage.ContainsFolderId($CurrentFolderID)) {\n            try {\n                # Get members of the group\n                $FolderCollaborationsResp = \"$(box folders:collaborations $CurrentFolderID --fields='accessible_by,role,id' --json 2>&1)\"\n                $FolderCollaborations = $FolderCollaborationsResp | ConvertFrom-Json\n\n                # Update FolderCollaborationStorage by adding list CollaborationGroup to particular folder id\n                $FolderCollaborationStorage.AddFolderId($CurrentFolderID)\n                $FolderCollaborations | Where-Object { $_.accessible_by.type -eq 'group' } | ForEach-Object { $FolderCollaborationStorage.AddCollaborationGroupForFolder([CollaborationGroup]::new($_), $CurrentFolderID)}\n\n                Write-Log \"Successfully fetched the collaborations of the folder with ID: $CurrentFolderID.\" -output true\n                Write-Log $FolderCollaborations\n            } catch {\n                Write-Log \"Could not fetch the collaborations of the folder with ID: $CurrentFolderID. See log for details. Skipping processing current row.\" -errorMessage $FolderCollaborationsResp -output true -color Red\n                continue\n            }\n        }\n\n\n        # Check if the group is already a collaborator to the folder\n        if($FolderCollaborationStorage.ContainsCollaborationGroup($CurrentGroupID, $CurrentFolderID))\n        {\n            $CollaborationGroup = $FolderCollaborationStorage.GetCollaborationGroup($CurrentGroupID, $CurrentFolderID)\n\n            # If the group is already a collaborator to the folder, check if it has the same role as in the CSV entry.\n            # If they are the same, skip processing the current line.\n            if($CollaborationGroup.Role -eq $CurrentCollaborationRole) {\n                Write-Log \"Group '$CurrentGroupName' (ID:$CurrentGroupID) is already a collaborator of folder ID: $CurrentFolderID with the same role '$CurrentCollaborationRole'. Skipping processing current row.\" -output true\n                continue\n            }\n            else {\n                # If the collaborator role is different from the CSV entry, check if -UpdateExistingCollabs switch is enabled to update existing collaboration. If it is, then update the collaboration with the role from CSV entry.\n                if ($UpdateExistingCollabs) {\n                    try {\n                        # Update collaboration with the new role defined in CSV\n                        $UpdatedCollaborationResp = \"$(box collaborations:update $CollaborationGroup.CollaborationId --role=$CurrentCollaborationRole --json 2>&1)\"\n                        $UpdatedCollaborationResp | ConvertFrom-Json | Out-Null\n\n                        # Update the role for this entry locally in FolderCollaborationStorage, to be up to date.\n                        # It is possible with this simple assignment, because $CollaborationGroup is a reference type.\n                        $CollaborationGroup.Role = $CurrentCollaborationRole\n\n                        Write-Log \"Successfully updated collaboration to folder with ID: $CurrentFolderID, with group: '$CurrentGroupName' (ID:$CurrentGroupID) and role: '$CurrentCollaborationRole'.\" -output true\n                        Write-Log $UpdatedCollaborationResp\n                    } catch {\n                        Write-Log \"Could not update collaboration to folder with ID: $CurrentFolderID, with group: '$CurrentGroupName' (ID:$CurrentGroupID) and role: '$CurrentCollaborationRole'. See log for details.\" -errorMessage $UpdatedCollaborationResp -output true -color Red\n                        continue\n                    }\n                }\n                else {\n                    # If the collaborator role is different from the CSV entry, but the -UpdateExistingCollabs switch is disabled,\n                    # skip processing current CSV row.\n                    Write-Log (\"Group '$CurrentGroupName' (ID:$CurrentGroupID) is already a collaborator of folder ID: $CurrentFolderID but with role '$($CollaborationGroup.Role)' instead of '$CurrentCollaborationRole'.\" +`\n                    \" If you want to update existing collaborations, run the script with the '-UpdateExistingCollabs' swith enabled. Skipping processing current row.\")` -output true\n                    continue\n                }\n            }\n        }\n        else {\n            # If the group is not a collaborator to the folder yet, then create this collaboration\n            try {\n                # Create collaboration\n                $CreatedCollaborationResp = \"$(box collaborations:create $CurrentFolderID folder --group-id=$CurrentGroupID --role=$CurrentCollaborationRole --json 2>&1)\"\n                $CreatedCollaboration = $CreatedCollaborationResp | ConvertFrom-Json\n\n                # Update collaboration storage by adding new CollaborationGroup item for particular folder\n                $CollaborationGroupItem = [CollaborationGroup]::new($CreatedCollaboration.id, $CreatedCollaboration.accessible_by.id, $CreatedCollaboration.role)\n                $FolderCollaborationStorage.AddCollaborationGroupForFolder($CollaborationGroupItem,$CurrentFolderID)\n\n                Write-Log \"Successfully created collaboration to folder with ID: $CurrentFolderID, with group: '$CurrentGroupName' (ID:$CurrentGroupID) and role: '$CurrentCollaborationRole' .\" -output true\n                Write-Log $CreatedCollaborationResp\n            } catch {\n                Write-Log \"Could not create collaboration to folder with ID: $CurrentFolderID, with group: '$CurrentGroupName' (ID:$CurrentGroupID) and role: '$CurrentCollaborationRole'. See log for details.\" -errorMessage $CreatedCollaborationResp -output true -color Red\n                continue\n            }\n        }\n    }\n\n    Write-Log \"Finish create collaborations.\" -output true\n}\n\n# Create groups and collaborations\nFunction Start-Group-Collabs-Creation-Script {\n    Write-Log \"Start Mass_Group_Creation script.\" -output true\n\n    # Get existing groups\n    try {\n        $GroupsResp = \"$(box groups --json 2>&1)\"\n        $Groups = $GroupsResp | ConvertFrom-Json\n\n        # Add groups to hashtable GroupsHashtable for later convenient access, where \"name\" is the key and \"id\" is a value.\n        $Groups | ForEach-Object { $GroupsHashtable[$_.name] = $_.id }\n    } catch {\n        Write-Log \"Could not get groups. See log for details.\" -errorMessage $GroupsResp -output true -color Red\n        break\n    }\n\n    # Get list of users\n    try {\n        $UsersResp = \"$(box users --fields='id,login,name,role' --json 2>&1)\"\n        $Users = $UsersResp | ConvertFrom-Json\n\n        if (($users.Length -eq 0) -or ($users.total_count -eq 0)) {\n            Write-Log \"No users found!\" -output true -color Red\n            break\n        }\n\n        # Add users to hashtable UsersHashtable for later convenient access, where \"login\" is the key and \"id\" is a value.\n        $Users | ForEach-Object { $UsersHashtable[$_.login] = $_.id }\n    } catch {\n        Write-Log \"Could not get user list. See log for details.\" -errorMessage $UsersResp -output true -color Red\n        break\n    }\n\n    if ($SkipGroupsUpdate) {\n        Write-Log \"Switch '-SkipGroupsUpdate' is enabled. Skipping groups update.\" -output true\n    } else {\n        # Update groups based on $UserGroupAdditionPath csv file\n        Update-Groups\n    }\n\n    if ($SkipCollabsCreation) {\n        Write-Log \"Switch '-SkipCollabsCreation' is enabled. Skipping collaboration creation.\" -output true\n    } else {\n        # Create collaborations based on $CollaborationsCreationPath csv file\n        Update-Collaborations\n    }\n\n    Write-Log \"Finish Mass_Group_Creation script.\" -output true\n}\n\n# Start function\nFunction Start-Script {\n    try {\n        $AnalyticsClientManager = [AnalyticsClientManager]::new($(Get-Script-Name).ToLower())\n        $AnalyticsClientManager.SetScriptAnalyticsClient()\n\n        Start-Group-Collabs-Creation-Script\n    } finally {\n        $AnalyticsClientManager.UnsetScriptAnalyticsClients()\n    }\n}\n\n# Ensure console output is UTF-8 so non-ASCII characters from Box CLI render correctly\n[Console]::OutputEncoding = [System.Text.Encoding]::UTF8\nStart-Script\n"
  },
  {
    "path": "examples/Mass Groups & Collaborations Update/README.md",
    "content": "# Mass Groups & Collaborations Update\n\n**For detailed script overview, please follow [this guide][user-guide].**\n\nCreates and updates collaboration groups,  adds role-based group access to folders.\nThe script consists of two parts described in detail in the sections below. You can run them both or use the optional flags to decide which part to run.\n\n1. The first part creates groups if they don't already exist, and adding users to them if they are not already there. It takes a .csv file from [UserGroupAdditionPath](/examples/Mass%20Groups%20%26%20Collaborations%20Update/Mass_Groups_Collabs_Update.ps1#L20) as input. As you can see in an example CSV file [User_Group_Addition.csv](/examples/Mass%20Groups%20%26%20Collaborations%20Update/User_Group_Addition.csv), each row defines a pair between a group and a user. So each group name can be used multiple times with different users, as well as user can be used multiple times with different groups.\nIf you want however to skip this part of creating groups, you just need to set a `-SkipGroupsUpdate` flag when running the script.\n\n   ```bash\n   Mass_Groups_Collabs_Update.ps1 -SkipGroupsUpdate\n   ```\n\n2. The second part creates collaborations for groups to the folders only if they don't already exist. It takes a .csv file from [CollaborationsCreationPath](/examples/Mass%20Groups%20%26%20Collaborations%20Update/Mass_Groups_Collabs_Update.ps1#L23) as input. As you can see in an example CSV file [Collaborations_Creation.csv](/examples/Mass%20Groups%20%26%20Collaborations%20Update/Collaborations_Creation.csv), each row defines a relation between a group `GroupName` and a folder `FolderId`. Then for each row, the script checks if this group exists and if it's not already added as a collaborator to the pointed folder.\nIf both of these conditions are met, then a new collaboration is created using the role defined in `CollaborationRole` column.\nIn case when you want to skip this part of creating collaborations, you just need to set a `-SkipCollabsCreation` flag when running the script.\n\n   ```bash\n   Mass_Groups_Collabs_Update.ps1 -SkipCollabsCreation\n   ```\n\n## Setup Pre-Requisites\n1. Clone this GitHub repo or download files from the `/examples` directory\n   ```bash\n   git clone https://github.com/box/boxcli.git\n   ```\n2. Install PowerShell or .Net core.\n   > If you encounter issues make sure you install both dotnet core and PowerShell\n    1. For MacOS & Linux, install the latest version of [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.2).\n    2. For Windows, Install the latest version of [dotnet core](https://dotnet.microsoft.com/download).\n    \n3. Test PowerShell by running the `pwsh` command in your terminal.\n    ```bash\n    pwsh\n    ```\n\n    ```\n    mikechen@mbp create-users-automation % pwsh\n    PowerShell 7.2.1\n    Copyright (c) Microsoft Corporation.\n\t\n    https://aka.ms/powershell\n    Type 'help' to get help.\n\t\n    PS /Users/mikechen>\n    ```\n\n\n4. Create an OAuth Application using the [CLI Setup Quick Start][oauth-guide].\n\n\n## 1. Script Parameters\n1. Update the [UserGroupAdditionPath](/examples/Mass%20Groups%20%26%20Collaborations%20Update/Mass_Groups_Collabs_Update.ps1#L20) to set your own Groups Update .csv file path. This .csv file should have two columns with the following headers: `GroupName` and `UserEmail`. The `UserEmail` column should contain the primary email address for the user in Box. The `GroupName` column should contain the name of the group. If the group with this name isn't exist, then it will be created.\n\n\tThis is an example input .csv:\n\t|GroupName |UserEmail              |\n\t|----------|-----------------------|\n\t|Group 1   | ManagedUser1@test.com |\n\t|Group 1   | ManagedUser2@test.com |\n\t|Group 2   | ManagedUser3@test.com |\n\t|Group 3   | ManagedUser1@test.com |\n\t|Group 3   | ManagedUser3@test.com |\n\n\n2. Update the [CollaborationsCreationPath](/examples/Mass%20Groups%20%26%20Collaborations%20Update/Mass_Groups_Collabs_Update.ps1#L23) to set your own Collaborations Creation .csv file path. This .csv file should have three columns with the following headers: `GroupName`, `FolderId` and `CollaborationRole`. The `GroupName` column should contain the name of the group, which will be added as a collaborator.  The `FolderId` column should contain ID of a folder to which the collaborator will be added to. The `CollaborationRole` column should contain the name of the role which will be used when creating collaboration.\n\n\tThis is an example input .csv:\n\t|GroupName |FolderId |CollaborationRole |\n\t|----------|---------|------------------|\n\t|Group 1   | 1111111 | editor           |\n\t|Group 2   | 1111111 | viewer_uploader  |\n\t|Group 2   | 2222222 | viewer           |\n\t|Group 3   | 1111111 | viewer_uploader  |\n\t|Group 3   | 3333333 | editor           |\n\t|Group 3   | 4444444 | editor           |\n\n3. Optional: There may be cases where a group has already been a collaborator for a specific folder, but with a role other than that defined in the CSV file.\nThis script will simply inform you about that case without making any change to existing collaboration. But if you want to update an existing collaboration with role defined in CSV file, you need to pass an additional switch `-UpdateExistingCollabs` when running the script.\n   ```bash\n   Mass_Groups_Collabs_Update.ps1 -UpdateExistingCollabs\n   ```\n\n\n4. Optional: To run the script only for groups updates (skipping collaboration creation), set the `-SkipCollabsCreation` boolean flag when running the script:\n   ```bash\n   Mass_Groups_Collabs_Update.ps1 -SkipCollabsCreation\n   ```\n\n5. Optional: To run the script only for collaborations creation (skipping groups updates), set the `-SkipGroupsUpdate` boolean flag when running the script:\n   ```bash\n   Mass_Groups_Collabs_Update.ps1 -SkipGroupsUpdate\n   ```\n\n###  Variables\n* `AvailableCollaborationRoles`: This variable defines all available roles that can be used in [Collaborations_Creation.csv](/examples/Mass%20Groups%20%26%20Collaborations%20Update/Collaborations_Creation.csv) file.\n\n\t```powershell\n\t$AvailableCollaborationRoles = @(\"editor\", \"viewer\", \"previewer\", \"uploader\", \"previewer_uploader\", \"viewer_uploader\", \"co-owner\")\n\t```\n\n## 2. Run the script\nNow all you need to do is run the script. Change the directory to the folder containing the script. In this example, it is the `Mass Groups & Collaborations Update` folder.\n```\nrvb@lab:~/box-cli/examples/Mass Groups & Collaborations Update$ pwsh\nPowerShell 7.2.4\nCopyright (c) Microsoft Corporation.\n\nhttps://aka.ms/powershell\nType 'help' to get help.\n\nPS /home/rvb/box-cli/examples/Mass Groups & Collaborations Update>\n```\n\nRun the script:\n```bash\n./Mass_Groups_Collabs_Update.ps1\n```\n\n## Logging\nLogs are stored in a `logs` folder located in the main folder. You have access to these log files:\n\n* `Mass_Groups_Collabs_Update_all.txt` that contains all log entries.\n* `Mass_Groups_Collabs_Update_errors.txt` that contains only errors.\n\n## Disclaimer\nThis project is a collection of open source examples and should not be treated as an officially supported product. Use at your own risk and as a source of example how to use Box CLI.\n\n[oauth-guide]: https://developer.box.com/guides/cli/quick-start/\n[user-guide]: https://developer.box.com/guides/cli/scripts/manage-groups-collaborations/\n"
  },
  {
    "path": "examples/Mass Groups & Collaborations Update/User_Group_Addition.csv",
    "content": "GroupName,UserEmail\nGroup 1,ManagedUser1@test.com\nGroup 1,ManagedUser2@test.com\nGroup 2,ManagedUser3@test.com\nGroup 3,ManagedUser1@test.com\nGroup 3,ManagedUser3@test.com\n"
  },
  {
    "path": "examples/Mass Update User Zones/Mass_Update_User_Zones.ps1",
    "content": "#APP SETUP\n#README: This powershell script will use the Box CLI to provision users to the specified data residency Zone.\n\n#APPLICATION ACCESS LEVEL (FOR JWT APPS): App + Enterprise Access\n#APPLICATION SCOPES: Manage Enterprise Properties, Manage Users, Generate User Access Tokens\n\n########################################################################################\n\nparam (\n    [switch]$DryRun = $false # if enabled, then no delete/create/update calls will be made, only read ones\n)\n\n########################################################################################\n###   SCRIPT CONFIG - MODIFY THESE FOR YOUR ENVIRONMENT   ##############################\n########################################################################################\n\n    # Set User Zones Update CSV Path\n    $UserZonesUpdatePath = \"./User_Zones_Update.csv\"\n\n    # Set login email address for the admin that will make user Zone assignments\n    $adminEmail = \"\"\n\n    # Customize zone mapping appropriate to your environment\n    $ZonesTable = @{\n        US = \"100001\"             #US\n        GermanyIreland = \"100002\" #Germany/Ireland with in region uploads/downloads/previews\n        Australia = \"100003\"      #Australia\n        Japan = \"100004\"          #Japan with in region uploads/downloads/previews\n        Canada = \"100005\"         #Canada\n        JapanSingapore = \"100007\" #Japan/Singapore with in region uploads/downloads/previews\n        GermanyUK = \"100008\"      #Germany/UK\n        UK = \"100009\"             #UK with in region uploads/downloads/previews\n        France = \"100012\"         #France\n    }\n\n########################################################################################\n###   SCRIPT BUSINESS LOGIC - MODIFY ANYTHING BELOW THIS POINT   #######################\n########################################################################################\n\n$EmailColumnName = \"Email\"   # email column name of csv input\n$RegionColumnName = \"Region\" # region column name of csv input\n\n# Get current script file name\nFunction Get-Script-Name() {\n    $filename = $MyInvocation.ScriptName | Split-Path -Leaf\n    if ($filename -match \".\") {\n        $filename = $filename.Substring(0, $filename.LastIndexOf(\".\"))\n    }\n\n    return $filename\n}\n\n# Function to write to logs\nFunction Write-Log { param ([string]$message, [string]$errorMessage = $null, [Exception]$exception = $null, [string]$output = $false, [string]$color = \"Green\")\n\n    # Define log level - Can be \"errors\" or \"all\"\n    $logLevel = \"all\"\n\n    # Create logs directory if it doesn't exist\n    if (-not (Test-Path \".\\logs\")) {\n        New-Item -Path . -Name \"logs\" -ItemType 'directory' > $null\n    }\n\n    $dateTime = Get-Date\n\n    # Set log filename to the name of the script\n    $logFilename = Get-Script-Name\n    $debugErrorFile = \".\\logs\\\" + $logFilename + \"_errors.txt\"\n    $debugAllFile = \".\\logs\\\" + $logFilename + \"_all.txt\"\n\n    if ($exception -or $errorMessage) {\n        $severity = \"ERROR\"\n    } else {\n        $severity = \"INFO\"\n    }\n\n    if ($exception.Response) {\n        $result = $exception.Response.GetResponseStream()\n        $reader = New-Object System.IO.StreamReader($result)\n        $reader.BaseStream.Position = 0\n        $reader.DiscardBufferedData()\n        $responseBody = $reader.ReadToEnd();\n    }\n\n    $logMessage = ($severity + \"`t\")\n    $logMessage += ($dateTime)\n    $logMessage += (\"`t\" + $message + \"`t\")\n\n    if ($exception) {\n        $logMessage += ($exception.Message + \"`t\")\n    }\n\n    if ($errorMessage) {\n        $logMessage += ($errorMessage + \"`t\")\n    }\n\n    if ($responseBody) {\n        $logMessage += (\"Box responded with: \" + $responseBody + \"`t\")\n    }\n\n    if ($output -eq \"true\") {\n        Write-Host $message -ForegroundColor $color\n    }\n\n    if ($logLevel -eq \"all\") {\n        $logMessage | Add-Content $debugAllFile\n\n        if ($severity -eq \"ERROR\") {\n            $logMessage | Add-Content $debugErrorFile\n        }\n    } else {\n        if ($severity -eq \"ERROR\") {\n            $logMessage | Add-Content $debugErrorFile\n        }\n    }\n}\n\n# This class is used for setting/restoring analytics client header when running this script\nclass AnalyticsClientManager {\n    [string]$TemporaryAnalyticsClientName\n    [string]$OriginalAnalyticsClientName\n    [bool]$IsOriginalAnalyticsClientEnabled\n\n    AnalyticsClientManager([string]$temporaryAnalyticsClientName) {\n        $this.TemporaryAnalyticsClientName = \"box_sample_scripts $($temporaryAnalyticsClientName)\"\n    }\n\n    [bool] IsAnalyticsClientSupported() {\n        return \"$(box configure:settings --help)\" -like \"*--analytics-client-name*--json*\"\n    }\n\n    [void] StoreOriginalSettings() {\n        $SettingsContent = \"$(box configure:settings --json)\" | ConvertFrom-Json\n\n        $this.OriginalAnalyticsClientName = $SettingsContent.AnalyticsClient.Name\n        if (!$this.OriginalAnalyticsClientName) {\n            $this.OriginalAnalyticsClientName = \"cli\"\n        }\n\n        if($SettingsContent.EnableanalyticsClient) {\n            $this.IsOriginalAnalyticsClientEnabled = $true\n        } else {\n            $this.IsOriginalAnalyticsClientEnabled = $false\n        }\n\n        Write-Log \"Stored original analytics client settings, name: $($this.OriginalAnalyticsClientName), enabled: $($this.IsOriginalAnalyticsClientEnabled).\" -output false\n    }\n\n    [void] RestoreOriginalSettings() {\n        if ($this.IsOriginalAnalyticsClientEnabled) {\n            $RestoreAnalyticsClientEnablementState = \"--enable-analytics-client\"\n        } else {\n            $RestoreAnalyticsClientEnablementState = \"--no-enable-analytics-client\"\n        }\n\n        \"$(box configure:settings $RestoreAnalyticsClientEnablementState --analytics-client-name=$($this.OriginalAnalyticsClientName))\"\n        Write-Log \"Restored original analytics client settings, name: $($this.OriginalAnalyticsClientName), enabled: $($this.IsOriginalAnalyticsClientEnabled).\" -output false\n    }\n\n    [void] SetScriptAnalyticsClient() {\n        if ($this.IsAnalyticsClientSupported()) {\n            $this.StoreOriginalSettings()\n\n            \"$(box configure:settings --enable-analytics-client --analytics-client-name=$($this.TemporaryAnalyticsClientName))\"\n            Write-Log \"Set temporarily analytics client settings, name: $($this.TemporaryAnalyticsClientName), enabled: true.\" -output false\n        }\n    }\n\n    [void] UnsetScriptAnalyticsClients() {\n        if ($this.IsAnalyticsClientSupported()) {\n            $this.RestoreOriginalSettings()\n        }\n    }\n}\n\n# Update User Zones\nFunction Start-User-Zones-Update-Script {\n    if ($DryRun) {\n        Write-Log \"Start Mass_Update_User_Zones script in DryRun mode\" -output false\n    } else {\n        Write-Log \"Start Mass_Update_User_Zones script\" -output false\n    }\n\n    # Get the admin user based on email login\n    if ($adminEmail -eq \"\") {\n        $adminEmail = Read-Host -Prompt \"Please enter the admin or a co-admin login email address\"\n    }\n    # Check if user exists and get user ID\n    try {\n        $adminUserObjResp = \"$(box users --filter=$adminEmail --fields='enterprise,role' --json 2>&1)\"\n        $adminUserObj = $adminUserObjResp | ConvertFrom-Json\n\n        if (($adminUserObj.Length -eq 0) -or $($adminUserObj.total_count) -eq 0){\n            Write-Log \"No user found for $adminEmail.\" -output true -color Yellow\n            break\n        } elseif ($($adminUserObj.total_count) -gt 1) {\n            Write-Log \"Multiple matching users found for $adminEmail. Skipping..\" -output true -color Yellow\n            break\n        } else {\n            Write-Log \"Found profile for $($adminUserObj.login) ($($adminUserObj.id))\" -output true\n        }\n    } catch {\n        Write-Log (\"Could not find matching user for $adminEmail. See log for details.\") -errorMessage $adminUserObjResp -output true -color Red\n        break\n    }\n\n    # Ensure use is admin or coadmin\n    if (($adminUserObj.role -ne \"admin\") -and ($adminUserObj.role -ne \"coadmin\")) {\n        Write-Log \"The specified user does not have admin or co-admin role\" -output true -color Yellow\n        break\n    }\n\n    # Get the admin id and enterprise id\n    $adminID = $adminUserObj.ID\n    $enterpriseId = $adminUserObj.enterprise.id\n    Write-Log \"Processing enterprise $enterpriseId\" -output false\n\n    # Read the input CSV\n    try {\n        $UsersToUpdate = Import-Csv $UserZonesUpdatePath\n        $NumUsersToUpdate = ($UsersToUpdate | Measure-Object).Count\n    } catch {\n        Write-Log \"Error reading user zone update CSV file\" -exception $_.Exception -output true -color Red\n        break\n    }\n\n    # Check if there are any users in the input\n    if (!$($NumUsersToUpdate -gt 0)) {\n        Write-Log \"No users to act upon\" -output true -color Yellow\n        break\n    }\n\n    # Check if input file has the correct format\n    $csvColumns = $UsersToUpdate | Get-Member -memberType 'NoteProperty' | Select-Object -ExpandProperty 'Name'\n    if (-not (($csvColumns -contains $EmailColumnName) -and ($csvColumns -contains $RegionColumnName))) {\n        Write-Log \"Input file requires 'Email' and 'Region' columns\" -output true -color Yellow\n        break;\n    }\n\n    Write-Host \"Number of Users to Process: $NumUsersToUpdate\" -ForegroundColor Green\n\n    # Get an access token scoped to the admin, to make Zone assignments\n    $adminToken = \"$(box tokens:get --user-id=$adminID)\"\n\n    # Get the default storage policy\n    try {\n        $EnterprisePolicyResp = \"$(box storage-policies:assignments:lookup $enterpriseId --type=enterprise --token=$adminToken --json 2>&1)\"\n        $EnterprisePolicy = $EnterprisePolicyResp | ConvertFrom-Json\n        $EnterprisePolicy = $EnterprisePolicy.storage_policy.id\n    } catch {\n        Write-Log \"Could not get the default Storage Policy for the enterprise. See log for details.\" -errorMessage $EnterprisePolicyResp -output true -color Red\n\n        break\n    }\n\n    ForEach($UserToUpdate in $UsersToUpdate) {\n\n        $UserEmail = $userObj = $null\n        $UserZone = $null\n\n        $UserEmail = $($UserToUpdate.$EmailColumnName)\n        $UserZone = $($UserToUpdate.$RegionColumnName)\n\n        Write-Log \"Starting script for $UserEmail...\" -output true -color White\n\n        # Check if user exists and get user ID\n        try {\n            $userObjResp = \"$(box users --filter=$UserEmail --json 2>&1)\"\n            $userObj = $userObjResp | ConvertFrom-Json\n\n            if (($userObj.Length -eq 0) -or $($userObj.total_count) -eq 0){\n                Write-Log \"No user found for $UserEmail. Skipping..\" -output true -color Yellow\n                Continue\n            } elseif ($($userObj.total_count) -gt 1){\n                Write-Log \"Multiple matching users found for $UserEmail. Skipping..\" -output true -color Yellow\n\n                Continue\n            } else {\n                Write-Log \"Found profile for $($userObj.login) ($($userObj.id))\" -output true\n            }\n        } catch {\n            Write-Log \"Could not find matching user for $UserEmail. The user may no longer exist. See log for details.\" -errorMessage $userObjResp -output true -color Red\n\n            continue\n        }\n\n        # Get user's storage policy assignment\n        try {\n            $userStoragePolicyResp = \"$(box storage-policies:assignments:lookup $userObj.id --token=$adminToken --json 2>&1)\"\n            $userStoragePolicy = $userStoragePolicyResp | ConvertFrom-Json\n\n            Write-Log (\"Found Storage Policy Assignment for $($userObj.login) ($($userObj.id)).\" +`\n            \" User assigned to Storage Policy with this id: $($userStoragePolicy.storage_policy.id)\") `\n        } catch {\n            Write-Log \"Could not find Storage Policy Assignment for $UserEmail. See log for details. \" -errorMessage $userStoragePolicyResp -output true -color Red\n\n            continue\n        }\n\n        # If the user is in the correct zone, move onto the next user\n        if ($($userStoragePolicy.storage_policy.id -eq $ZonesTable[$UserZone])){\n            Write-Log (\"User $($userObj.login) ($($userObj.id)) is already assigned\" +`\n            \" to the specified zone: $UserZone ($($ZonesTable[$UserZone])).\" +`\n            \" No action required.\") `\n            -output true\n\n            continue\n        } else {\n            # If the user's current storage policy is inherited from the enterprise, create a new assignment\n            if ($($userStoragePolicy.assigned_to.type -eq \"enterprise\")) {\n                try {\n                    if (!$DryRun) {\n                        $assignmentObjResp = \"$(box storage-policies:assign $ZonesTable[$UserZone] $userObj.id --token=$adminToken --json 2>&1)\"\n                        $assignmentObj = $assignmentObjResp | ConvertFrom-Json\n\n                        Write-Log (\"Successfully assigned $($userObj.login) ($($userObj.id))\" +`\n                        \" to the specified zone: $UserZone ($($ZonesTable[$UserZone])).\" +`\n                        \" Assignment id: $($assignmentObj.id)\") `\n                        -output true\n                    } else {\n                        Write-Log (\"`\"DryRun`\" mode is enabled. Script would have assigned $($userObj.login) ($($userObj.id))\" +`\n                        \" to the specified zone: $UserZone ($($ZonesTable[$UserZone])).\") `\n                        -output true\n                    }\n                } catch {\n                    Write-Log (\"Could not assign $($userObj.login) ($($userObj.id))\" +`\n                    \" to the specified zone: $UserZone ($($ZonesTable[$UserZone])). See log for details.\") -errorMessage $assignmentObjResp -output true -color Red\n\n                    continue\n                }\n            } else {\n                # If the target zone is the same as the enterprise default zone, delete the current policy assignment\n                if ($($ZonesTable[$UserZone] -eq $EnterprisePolicy)){\n                    try {\n                        if (!$DryRun) {\n                            \"$(box storage-policies:assignments:remove $userStoragePolicy.id --token=$adminToken)\"\n\n                            Write-Log (\"Successfully reassigned $($userObj.login) ($($userObj.id))\" +`\n                            \" to the specified zone: $UserZone ($($ZonesTable[$UserZone])).\") `\n                            -output true\n                        } else {\n                            Write-Log (\"`\"DryRun`\" mode is enabled. Script would have reassigned $($userObj.login) ($($userObj.id))\" +`\n                            \" to the specified zone: $UserZone ($($ZonesTable[$UserZone])).\") `\n                            -output true\n                        }\n                    } catch {\n                        Write-Log (\"Could not reassign $($userObj.login) ($($userObj.id))\" +`\n                        \" to the specified zone: $UserZone ($($ZonesTable[$UserZone])). See log for details.\") -exception $_.Exception -output true -color Red\n\n                        continue\n                    }\n                # Else reassign the user to the specified zone\n                } else {\n                    try {\n                        if (!$DryRun) {\n                            $assignmentObjResp = \"$(box storage-policies:assign $ZonesTable[$UserZone] $userObj.id --token=$adminToken --json 2>&1)\"\n                            $assignmentObj = $assignmentObjResp | ConvertFrom-Json\n\n                            Write-Log (\"Successfully reassigned $($userObj.login) ($($userObj.id))\" +`\n                            \" to the specified zone: $UserZone ($($ZonesTable[$UserZone])).\" +`\n                            \" Assignment id: $($assignmentObj.id)\") `\n                            -output true\n                        } else {\n                            Write-Log (\"`\"DryRun`\" mode is enabled. Script would have reassigned $($userObj.login) ($($userObj.id))\" +`\n                            \" to the specified zone: $UserZone ($($ZonesTable[$UserZone])).\") `\n                            -output true\n                        }\n                    } catch {\n                        Write-Log (\"Could not reassign $($userObj.login) ($($userObj.id))\" +`\n                        \" to the specified zone: $UserZone ($($ZonesTable[$UserZone])). See log for details.\") -errorMessage $assignmentObjResp -output true -color Red\n\n                        continue\n                    }\n                }\n            }\n        }\n    } #End foreach\n\n    Write-Log \"Finish Mass_Update_User_Zones script.\"\n}\n\n# Start function\nFunction Start-Script {\n    try {\n        $AnalyticsClientManager = [AnalyticsClientManager]::new($(Get-Script-Name).ToLower())\n        $AnalyticsClientManager.SetScriptAnalyticsClient()\n\n        Start-User-Zones-Update-Script\n    } finally {\n        $AnalyticsClientManager.UnsetScriptAnalyticsClients()\n    }\n}\n\n# Ensure console output is UTF-8 so non-ASCII characters from Box CLI render correctly\n[Console]::OutputEncoding = [System.Text.Encoding]::UTF8\nStart-Script\n"
  },
  {
    "path": "examples/Mass Update User Zones/README.md",
    "content": "# Mass Update User Zones #\n\n**For detailed script overview, please follow [this guide][user-guide].**\n\nProvisions users to specified data residency Zones within a Multizone Box tenant. It performs the following steps:\n\n1. It uses admin or co-admin login email address to find the associated enterprise and the zone policy assigned to this enterprise. An assigned zone policy is inherited by all users unless specified otherwise. It is sometimes called the **default zone**.\n2. It performs zone assignment based on an input `.csv` file containing user email addresses and zone mappings.\nUsually, you use the script once to do the initial provisioning of user zones, but you can also use it for subsequent runs to make zone assignment updates.\n\nIf you would like to use Admin Console for zone assignment, see [here](https://support.box.com/hc/en-us/articles/360044193533-Assigning-Zones-through-the-Admin-Console). For more information about Box Zones, see the [official website](https://www.box.com/zones).\n\n## Setup Pre-Requisites\n1. Clone this github repo or download files from the `/examples` directory\n   ```bash\n   git clone https://github.com/box/boxcli.git\n   ```\n2. Install PowerShell or .Net core.\n   > If you encounter issues make sure you install both dotnet core and PowerShell\n    1. For MacOS & Linux, Install the latest version of [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.2).\n    2. For Windows, Install the latest version of [dotnet core](https://dotnet.microsoft.com/download).\n    \n3. Test PowerShell by running the `pwsh` command in your terminal.\n    ```bash\n    pwsh\n    ```\n\n    ```\n    mikechen@mbp create-users-automation % pwsh\n    PowerShell 7.2.1\n    Copyright (c) Microsoft Corporation.\n\t\n    https://aka.ms/powershell\n    Type 'help' to get help.\n\t\n    PS /Users/mikechen>\n    ```\n\n4. Setting up the CLI requires creating a Box platform application that uses server authentication with JWT. See the [Box CLI Using JWT Authentication][jwt-cli] page for instructions. \n    * The Box platform application must have the following application **access level** enabled in the configuration page: `App + Enterprise Access`\n    * The Box application must have the following **application scopes** enabled in the configuration page: `Manage Enterprise Properties`, `Manage Users`\n    * The Box application must have the following **advanced features** enabled in the configuration page: `Generate User Access Tokens`\n\n5. The  **Box Admin** or **Co-Admin Account** user must have `Manage Users` privileges at a minimum.\n\n\n## 1. Script Parameters\n1. Update the [UserZonesUpdatePath][UserZonesUpdatePath-param] to set your own User Zones Update `.csv` file path. The `.csv` file must have two columns with the following headers: **Email** and **Region**.\n   * **Email** contains the primary email address of a Box user.\n   * **Region**  contains the user-friendly name for the zone to which the script will assign the user. This name is provided by the [ZonesTable][zonestable] that is a hash table used to define zones. The keys are the zone's user-friendly names, and the corresponding value is the global ID of the zone.\n\n     ```bash\n     $ZonesTable = @{\n     US = \"100001\"             #US\n     GermanyIreland = \"100002\" #Germany/Ireland with in region uploads/downloads/previews\n     Australia = \"100003\"      #Australia\n     Japan = \"100004\"          #Japan with in region uploads/downloads/previews\n     Canada = \"100005\"         #Canada\n     JapanSingapore = \"100007\" #Japan/Singapore with in region uploads/downloads/previews\n     GermanyUK = \"100008\"      #Germany/UK\n     UK = \"100009\"             #UK with in region uploads/downloads/previews\n     France = \"100012\"         #France\n     }\n     ```\n     \n\n   > Consult the BC or CSM contact to get the IDs corresponding to the zones enabled in a specific enterprise.\n\n   A [sample input][example-csv] `.csv` file containing emails and zone names is provided with this script. Its content looks as follows:\n\n   | Email|Region|\n   |------|-------|\n   |betty@company.com|US|\n   |roger@company.com|France|\n   |sally@company.com|JapanSingapore|   \n\n\n2. Update the [adminEmail][adminEmail-param] to the admin or co-admin login email address of the account that will be used to make zone assignments.  If you don't specify this value, the script will prompt you for it.\n3. Optional: To run the script in dry run mode, set the `DryRun` boolean flag when running the script:\n`./Mass_Update_User_Zones.ps1 -DryRun`.\n Dry run doesn't mean that API calls won't be made, instead any create/update/delete calls will be skipped only.\n\n## 2. Run the script\nChange the directory to the folder containing the script.\nIn this example, it is the `Mass Update User Zones` folder.\n\n```\nrvb@lab:~/box-cli/examples/Mass Update User Zones$ pwsh\nPowerShell 7.2.4\nCopyright (c) Microsoft Corporation.\n\nhttps://aka.ms/powershell\nType 'help' to get help.\n\nPS /home/rvb/box-cli/examples/Mass Update User Zones>\n```\n\nRun the script:\n```bash\n./Mass_Update_User_Zones.ps1\n```\n\n## Logging\nLogs are stored in a `logs` folder located in the main folder. You have access to these log files:\n\n* `Mass_Update_User_Zones_all.txt` that contains all log entries.\n* `Mass_Update_User_Zones_errors.txt` that contains only errors.\n\n## Disclaimer\nThis project is a collection of open source examples and should not be treated as an officially supported product. Use at your own risk and as a source of example how to use Box CLI.\n\n[oauth-guide]: https://developer.box.com/guides/cli/quick-start/\n[jwt-cli]: https://developer.box.com/guides/cli/cli-docs/jwt-cli/\n[UserZonesUpdatePath-param]: /examples/Mass%20Update%20User%20Zones/Mass_Update_User_Zones.ps1#L18\n[example-csv]: User_Zones_Update.csv\n[zonestable]:/examples/Mass%20Update%20User%20Zones/Mass_Update_User_Zones.ps1#L23\n[adminEmail-param]: /examples/Mass%20Update%20User%20Zones/Mass_Update_User_Zones.ps1#L21\n[user-guide]: https://developer.box.com/guides/cli/scripts/user-zones-mass-update/\n"
  },
  {
    "path": "examples/Mass Update User Zones/User_Zones_Update.csv",
    "content": "﻿Email,Region\nbetty@company.com,US\nroger@company.com,France\nsally@company.com,JapanSingapore\n"
  },
  {
    "path": "examples/Metadata Extraction/Metadata-extraction.ps1",
    "content": "#README: This powershell script will extract all metadata (all templates) from all files in user inputted folder ID and generate separate CSV's for each metadata template.\n\n#APP SETUP\n#APPLICATION ACCESS LEVEL (FOR JWT APPS): App + Enterprise Access\n#APPLICATION SCOPES: Read & Write all folders stored in Box, Manage users, & Make API calls using the as-user header\n\n#############################################################################\n\nparam (\n# Set specific folder ID in which to get metadata values from\n    [string]$FolderID = \"\",\n\n# Set to a specific Box user id if you would like to pull metadata as a specific user instead of the current user\n    [string]$UserId = \"\",\n\n# If enabled, the \"displayName\" of the metadata template field will be used as the header instead of the \"key\"\n    [switch]$UseDisplayName = $false\n)\n\n#############################################################################\n\n# Get current script file name\nFunction Get-Script-Name()\n{\n    $filename = $MyInvocation.ScriptName | Split-Path -Leaf\n    if ($filename -match \".\")\n    {\n        $filename = $filename.Substring(0,$filename.LastIndexOf(\".\"))\n    }\n\n    return $filename\n}\n\n# Function to write to logs\nFunction Write-Log\n{\n    param ([string]$message, [string]$errorMessage = $null, [Exception]$exception = $null, [string]$output = $false, [string]$color = \"Green\")\n\n    # Define log level - Can be \"errors\" or \"all\"\n    $logLevel = \"all\"\n\n    # Create logs directory if it doesn't exist\n    if (-not(Test-Path \".\\logs\"))\n    {\n        New-Item -Path . -Name \"logs\" -ItemType 'directory' > $null\n    }\n\n    $dateTime = Get-Date\n\n    # Set log filename to the name of the script\n    $logFilename = Get-Script-Name\n    $debugErrorFile = \".\\logs\\\" + $logFilename + \"_errors.txt\"\n    $debugAllFile = \".\\logs\\\" + $logFilename + \"_all.txt\"\n\n    if ($exception -or $errorMessage)\n    {\n        $severity = \"ERROR\"\n    }\n    else\n    {\n        $severity = \"INFO\"\n    }\n\n    if ($exception.Response)\n    {\n        $result = $exception.Response.GetResponseStream()\n        $reader = New-Object System.IO.StreamReader($result)\n        $reader.BaseStream.Position = 0\n        $reader.DiscardBufferedData()\n        $responseBody = $reader.ReadToEnd();\n    }\n\n    $logMessage = ($severity + \"`t\")\n    $logMessage += ($dateTime)\n    $logMessage += (\"`t\" + $message + \"`t\")\n\n    if ($exception)\n    {\n        $logMessage += ($exception.Message + \"`t\")\n    }\n\n    if ($errorMessage)\n    {\n        $logMessage += ($errorMessage + \"`t\")\n    }\n\n    if ($responseBody)\n    {\n        $logMessage += (\"Box responded with: \" + $responseBody + \"`t\")\n    }\n\n    if ($output -eq \"true\")\n    {\n        Write-Host $message -ForegroundColor $color\n    }\n\n    if ($logLevel -eq \"all\")\n    {\n        $logMessage | Add-Content $debugAllFile\n\n        if ($severity -eq \"ERROR\")\n        {\n            $logMessage | Add-Content $debugErrorFile\n        }\n    }\n    else\n    {\n        if ($severity -eq \"ERROR\")\n        {\n            $logMessage | Add-Content $debugErrorFile\n        }\n    }\n}\n\n# This class is used for setting/restoring analytics client header when running this script\nclass AnalyticsClientManager\n{\n    [string]$TemporaryAnalyticsClientName\n    [string]$OriginalAnalyticsClientName\n    [bool]$IsOriginalAnalyticsClientEnabled\n\n    AnalyticsClientManager([string]$temporaryAnalyticsClientName)\n    {\n        $this.TemporaryAnalyticsClientName = \"box_sample_scripts $( $temporaryAnalyticsClientName )\"\n    }\n\n    [bool]\n    IsAnalyticsClientSupported()\n    {\n        return \"$( box configure:settings --help )\" -like \"*--analytics-client-name*--json*\"\n    }\n\n    [void]\n    StoreOriginalSettings()\n    {\n        $SettingsContent = \"$( box configure:settings --json )\" | ConvertFrom-Json\n\n        $this.OriginalAnalyticsClientName = $SettingsContent.AnalyticsClient.Name\n        if (!$this.OriginalAnalyticsClientName)\n        {\n            $this.OriginalAnalyticsClientName = \"cli\"\n        }\n\n        if ($SettingsContent.EnableanalyticsClient)\n        {\n            $this.IsOriginalAnalyticsClientEnabled = $true\n        }\n        else\n        {\n            $this.IsOriginalAnalyticsClientEnabled = $false\n        }\n\n        Write-Log \"Stored original analytics client settings, name: $( $this.OriginalAnalyticsClientName ), enabled: $( $this.IsOriginalAnalyticsClientEnabled ).\" -output false\n    }\n\n    [void]\n    RestoreOriginalSettings()\n    {\n        if ($this.IsOriginalAnalyticsClientEnabled)\n        {\n            $RestoreAnalyticsClientEnablementState = \"--enable-analytics-client\"\n        }\n        else\n        {\n            $RestoreAnalyticsClientEnablementState = \"--no-enable-analytics-client\"\n        }\n\n        \"$( box configure:settings $RestoreAnalyticsClientEnablementState --analytics-client-name=$($this.OriginalAnalyticsClientName) )\"\n        Write-Log \"Restored original analytics client settings, name: $( $this.OriginalAnalyticsClientName ), enabled: $( $this.IsOriginalAnalyticsClientEnabled ).\" -output false\n    }\n\n    [void]\n    SetScriptAnalyticsClient()\n    {\n        if ( $this.IsAnalyticsClientSupported())\n        {\n            $this.StoreOriginalSettings()\n\n            \"$( box configure:settings --enable-analytics-client --analytics-client-name=$($this.TemporaryAnalyticsClientName) )\"\n            Write-Log \"Set temporarily analytics client settings, name: $( $this.TemporaryAnalyticsClientName ), enabled: true.\" -output false\n        }\n    }\n\n    [void]\n    UnsetScriptAnalyticsClients()\n    {\n        if ( $this.IsAnalyticsClientSupported())\n        {\n            $this.RestoreOriginalSettings()\n        }\n    }\n}\n\n#############################################################################\n# Prompt for params if some are missing\nif (-not$FolderID)\n{\n    Write-Log \"Please enter the ID of the folder to extract metadata from:\" -output true -color Yellow\n    $FolderID = Read-Host\n}\n\nif (-not$UserId)\n{\n    Write-Log \"Please specify the user ID  to pull metadata as a specific user\" -output true -color Yellow\n    Write-Log \"Press Enter if you want to run script as the current user.\" -output true -color Yellow\n    $UserId = Read-Host \"User ID\"\n}\n\nFunction Start-Metadata-Extraction {\n\n    Write-Log \"Pulling data from Folder ID: $FolderID\" -output true -color Green\n\n    try {\n        #Pull all Items ID values from Folder ID\n        If (!$UserId) {\n            #Run as default user\n            Write-Log \"No user ID specified. Using current user.\" -output true -color Yellow\n            $EntriesResp = (box folders:items $FolderID --json 2>&1)\n        }\n        Else {\n            Write-Log \"Extracting metadata as user ID: $UserId\" -output true -color Yellow\n            #Run with as-user header with inputted User ID\n            $EntriesResp = (box folders:items $FolderID --as-user=$UserId --json 2>&1)\n        }\n\n        $Entries = $EntriesResp | ConvertFrom-Json\n    }\n    catch {\n        Write-Log \"Could not get the folder items. See error log for details.\" -errorMessage $EntriesResp -output True -color Red\n        break\n    }\n\n    Write-Log \"Output $($Entries | Out-String)\"\n    $MetadataTemplatesHashmap = @{}\n    $HeaderFieldName = If ($UseDisplayName) { 'displayName' } Else { 'key' }\n\n    ForEach ($Item in $Entries) {\n        $ItemID = $Item.id\n        Write-Log \"Reading Item ID: $ItemID\" -output true -color Green\n\n        #Pull Metadata values from Folder ID's\n        try {\n            If (!$UserId) {\n                #Run as default user (service account)\n                If ($Item.type -eq 'file') {\n                    $MetadataResp = (box files:metadata $ItemID --json 2>&1)\n                }\n                elseif ($Item.type -eq 'folder') {\n                    $MetadataResp = (box folders:metadata $ItemID --json 2>&1)\n                }\n            }\n            Else {\n                #Run with as-user header with inputted User ID\n                If ($Item.type -eq 'file') {\n                    $MetadataResp = (box files:metadata $ItemID --as-user=$UserId --json 2>&1)\n                }\n                elseif ($Item.type -eq 'folder') {\n                    $MetadataResp = (box folders:metadata $ItemID --as-user=$UserId --json 2>&1)\n                }\n            }\n            $Metadata = $MetadataResp | ConvertFrom-Json\n        }\n        catch {\n            Write-Log \"Could not get the metadata for item. See error log for details.\" -errorMessage $MetadataResp -output True -color Red\n            continue\n        }\n\n\n        #Loop through each metadata entry to add additional folder info & separate according to metadata template\n        ForEach ($MetadataValue in $Metadata) {\n            $TemplateKey = $MetadataValue.\"`$template\"\n\n            #Pull MetadataTemplate to get access to all it's fields and put it in a hashmap.\n            if (!$MetadataTemplatesHashmap.ContainsKey($TemplateKey)) {\n                Write-Log \"Pulling MetadataTemplate for templateKey: $TemplateKey\" -output true -color Green\n                Try {\n                    if (!$UserId) {\n                        $MetadataTemplateResp = (box metadata-templates:get $TemplateKey --json 2>&1)\n                    } else {\n                        $MetadataTemplateResp = (box metadata-templates:get $TemplateKey --as-user=$UserId --json 2>&1)\n                    }\n\n                    $MetadataTemplate = $MetadataTemplateResp | ConvertFrom-Json\n                    $MetadataTemplatesHashmap[$TemplateKey] = $MetadataTemplate\n                }  Catch {\n                    Write-Log \"Could not get the metadata template for item. See error log for details.\" -errorMessage $MetadataTemplateResp -output True -color Red\n                }\n            }\n\n            #Prepare the MetadataValue object by setting its fields name based on the passed UseDisplayName flag,\n            #which determines the name of the field used in the variable HeaderFieldName.\n            foreach ($MetadataTemplateField in $MetadataTemplatesHashmap[$TemplateKey].fields){\n                #To maintain the continuity of fields from the metadata template in the resulting CSV file, we remove and then add them at the end\n                if ($MetadataValue.PSObject.Properties.Name -contains $($MetadataTemplateField.key)) {\n                    $metadataFieldValue = $MetadataValue.$($MetadataTemplateField.key);\n                    $MetadataValue.PSObject.Properties.Remove($($MetadataTemplateField.key));\n                    $MetadataValue | Add-Member -NotePropertyName \"$($MetadataTemplateField.$HeaderFieldName)\" -NotePropertyValue $metadataFieldValue;\n                } else {\n                    #We add a field with an empty value so that it's included in the CSV file header, ensuring that subsequent items with this field will also be added\n                    $MetadataValue | Add-Member -NotePropertyName \"$($MetadataTemplateField.$HeaderFieldName)\" -NotePropertyValue $null;\n                }\n            }\n\n            #Append Object Info values: Name, Object Id, Type\n            $MetadataValue | Add-Member -NotePropertyName \"Name\" -NotePropertyValue $Item.name;\n            $MetadataValue | Add-Member -NotePropertyName \"Object Id\" -NotePropertyValue $Item.id;\n            $MetadataValue | Add-Member -NotePropertyName \"Type\" -NotePropertyValue $Item.type;\n\n            #Export metadata values to separate csv's according to metadata template keys\n            $MetadataValue | Export-Csv -Path ./MetadataTemplate_$Templatekey`.csv -Append -Force -NoTypeInformation\n            Write-Log \"Metadata saved to: MetadataTemplate_$Templatekey.csv\" -output true -color Green\n        }\n    }\n}\n\n# Start function\nFunction Start-Script {\n    try {\n        $AnalyticsClientManager = [AnalyticsClientManager]::new($( Get-Script-Name ).ToLower())\n        $AnalyticsClientManager.SetScriptAnalyticsClient()\n\n        Start-Metadata-Extraction\n    }\n    finally {\n        $AnalyticsClientManager.UnsetScriptAnalyticsClients()\n    }\n}\n\n# Ensure console output is UTF-8 so non-ASCII characters from Box CLI render correctly\n[Console]::OutputEncoding = [System.Text.Encoding]::UTF8\nStart-Script\n"
  },
  {
    "path": "examples/Metadata Extraction/README.md",
    "content": "# Extract metadata\n\nExtracts metadata details for all the files and folders in any Box folder and save that report as a CSV spreadsheet for each metadata template.\n\n## Setup Pre-Requisites\n1. Clone this github repo or download files from the `/examples` directory\n   ```bash\n   git clone https://github.com/box/boxcli.git\n   ```\n2. Install PowerShell or .Net core.\n   > If you encounter issues make sure you install both dotnet core and PowerShell\n\t1. For MacOS & Linux, Install the latest version of [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.2).\n\t2. For Windows, Install the latest version of [dotnet core](https://dotnet.microsoft.com/download).\n\n3. Test PowerShell by running the `pwsh` command in your terminal.\n    ```bash\n    pwsh\n    ```\n\n    ```\n    mikechen@mbp create-users-automation % pwsh\n    PowerShell 7.2.1\n    Copyright (c) Microsoft Corporation.\n\t\n    https://aka.ms/powershell\n    Type 'help' to get help.\n\t\n    PS /Users/mikechen>\n    ```\n4. Create an OAuth Application following the [CLI Setup Quick Start][oauth-guide].\n\n## 1. Script Parameters\n1. Set the [folderID][folderID-param] you want the script to scan for metadata details.\n2. Optional: To run the script as another user, set [userId][UserId-param] parameter.\n3. Optional: Use the [-UseDisplayName][UseDisplayName-param] switch when running the script to ensure that the headers of the resulting file correspond to the `displayName` field instead of the `key` in the metadata template.\n\n\n## 2. Run the script\n\nChange the directory to the folder containing the script. In this example, it is the `Metadata Extraction` folder.\n```pwsh\nrvb@lab:~/box-cli/examples/Metadata Extraction$ pwsh\nPowerShell 7.2.4\nCopyright (c) Microsoft Corporation.\n\nhttps://aka.ms/powershell\nType 'help' to get help.\n\nPS /home/rvb/box-cli/examples/Metadata Extraction>\n```\n\nRun the script:\n```pwsh\n./Metadata-extraction.ps1 -folderId 173961139760 -userId 20718545815\n```\nIf you don't specify parameters, the script will prompt you to enter it.\n\nWhen the script run is completed, you will see the following\noutput or a similar one.\n\n```\nPulling data from Folder ID: 173961139760\nExtracting metadata as user ID: 20718545815\nReading Item ID: 1016853559790\nMetadata saved to: MetadataTemplate_properties.csv\n```\n\n## Logging\nLogs are stored in a `logs` folder located in the main folder. You have access to these log files:\n\n* `Metadata-extraction_all.txt` that contains all log entries.\n* `Metadata-extraction_errors.txt` that contains only errors.\n\n## Disclaimer\nThis project is a collection of open source examples and should not be treated as an officially supported product. Use at your own risk and as a source of example how to use Box CLI.\n\n[oauth-guide]: https://developer.box.com/guides/cli/quick-start/\n[FolderID-param]: /examples/Metadata%20Extraction/Metadata-extraction.ps1#L11\n[UserID-param]: /examples/Metadata%20Extraction/Metadata-extraction.ps1#L14\n[UseDisplayName-param]: /examples/Metadata%20Extraction/Metadata-extraction.ps1#L17\n"
  },
  {
    "path": "examples/README.md",
    "content": "# CLI Sample scripts library\n\nThe [examples](/examples) directory contains a list of helpful CLI scripts for common use cases written in PowerShell (running on PowerShell 5 and 7) and Bash (upcoming)\n\nThere are the following scripts available:\n1. [Provision users and folders](/examples/User%20Creation%20%26%20Provisioning)\n2. [Update user zones](/examples/Mass%20Update%20User%20Zones)\n3. [Deprovision users and archive folders](/examples/User%20Deprovisioning)\n4. [Report Inactive Users](/examples/Inactive%20Users%20Report)\n5. [Manage Groups and Collaborations](/examples/Mass%20Groups%20%26%20Collaborations%20Update)\n6. [Extract metadata](/examples/Metadata%20Extraction)\n7. [Integration Mappings](/examples/Integration%20Mappings/)\n\n## Disclaimer\nThis folder is a collection of open source examples and should not be treated as an officially supported product. Use at your own risk and as a source of example how to use Box CLI.\n"
  },
  {
    "path": "examples/User Creation & Provisioning/Employees_1.csv",
    "content": "﻿firstName,lastName,email,username\r\nTest,User 1,ManagedUser1@demo.com,manageduser1\r\n"
  },
  {
    "path": "examples/User Creation & Provisioning/Employees_10.csv",
    "content": "﻿firstName,lastName,email,username\r\nManaged,User 1,ManagedUser1@test.com,manageduser1\r\nManaged,User 2,ManagedUser2@test.com,manageduser2\r\nManaged,User 3,ManagedUser3@test.com,manageduser3\r\nManaged,User 4,ManagedUser4@test.com,manageduser4\r\nManaged,User 5,ManagedUser5@test.com,manageduser5\r\nManaged,User 6,ManagedUser6@test.com,manageduser6\r\nManaged,User 7,ManagedUser7@test.com,manageduser7\r\nManaged,User 8,ManagedUser8@test.com,manageduser8\r\nManaged,User 9,ManagedUser9@test.com,manageduser9\r\nManaged,User 10,ManagedUser10@test.com,manageduser10"
  },
  {
    "path": "examples/User Creation & Provisioning/Employees_5.csv",
    "content": "﻿firstName,lastName,email,username\nManaged,User 1,ManagedUser1@demo.com,manageduser1\nManaged,User 2,ManagedUser2@demo.com,manageduser2\nManaged,User 3,ManagedUser3@demo.com,manageduser3\nManaged,User 4,ManagedUser4@demo.com,manageduser4\nManaged,User 5,ManagedUser5@demo.com,manageduser5\n"
  },
  {
    "path": "examples/User Creation & Provisioning/Folder_Structure.json",
    "content": "[\n    {\n        \"name\": \"Market Research\",\n        \"children\": [\n            {\n                \"name\": \"Statistics\",\n                \"children\": [\n                    {\n                        \"name\": \"Computed\",\n                        \"children\": []\n                    }\n                ]\n            }\n        ]\n    },\n    {\n        \"name\": \"Sales Plays\",\n        \"children\": [\n            {\n                \"name\": \"Big Pharma\",\n                \"children\": []\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "examples/User Creation & Provisioning/README.md",
    "content": "# Provision users and folders\n\nThis PowerShell script uses the Box CLI to build and create a personal folder structure, create managed users in bulk, and provision such new users by adding them to the newly created folder structure as collaborators with viewer or uploader roles.\n\n**For detailed script overview, please follow [this guide](https://developer.box.com/guides/cli/quick-start/powershell-script-templates/).**\n\n## Setup Pre-Requisites\n1. Clone this github repo or download files from the `/examples` directory.\n\t```bash\n\tgit clone https://github.com/box/boxcli.git\n\t```\n2. Install PowerShell or .Net core.\n\t> If you encounter issues make sure you install both dotnet core and PowerShell\n    1. For MacOS & Linux, Install the latest version of [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.2).\n    2. For Windows, Install the latest version of [dotnet core](https://dotnet.microsoft.com/download).\n\t\n3. Test PowerShell by running the `pwsh` command in your terminal.\n\t```bash\n\tpwsh\n\t```\n\t\n\tYou will see similar output:\n\t```\n\tmikechen@mbp create-users-automation % pwsh\n\tPowerShell 7.2.1\n\tCopyright (c) Microsoft Corporation.\n\n\thttps://aka.ms/powershell\n\tType 'help' to get help.\n\n\tPS /Users/mikechen>\n\t```\n\n4. Create an OAuth Application using the [CLI Setup Quick Start][oauth-guide].\n\n## Configure the script\n### Update the list of employee accounts for creation\n\nThe header row should look like the below:\n\nfirstName,lastName,email,username\n\nNOTE 1 - EMAILS MUST BE UNIQUE ACROSS ALL OF BOX - CANNOT CREATE EMAILS USED PREVIOUSLY\n\nNOTE 2 - USERNAME MUST BE UNIQUE ACROSS YOUR BOX INSTANCE. - THIS IS USED FOR THE PERSONAL FOLDER NAME\n\nFor example, update the [employees_5.csv](/examples/User%20Creation%20%26%20Provisioning/Employees_5.csv) with the following data:\n```\nManaged,User 1,ManagedUser1@test.com,manageduser1\nManaged,User 2,ManagedUser2@test.com,manageduser2\nManaged,User 3,ManagedUser3@test.com,manageduser3\n```\n### List of parameters\n\n- `EmployeeList`: Path to Employee List CSV.\n- `PersonalFolderParentID`: Destination folder ID for all personal folders to be created in, either when using JSON file as input to create folder structure, or uploading local structure. This folder should be made prior to running the script the first time. It is not advised to make this value 0, as this will create individual Personal folders in root of the account you set up the cli with.\n- `FolderStructureJSONPath`: Your own Folder Structure JSON Path. \n- `PersonalFolderSlug`. Ending name of the folder that will be created as parent for folders from JSON structure. It's set to `Personal Folder` by default, but feel free to set it to your needs. The username is concatenated with this value to create each user's personal folder name. ex - `rsmith2's Personal Folder`.\n- `LocalUploadPath`: Local directory to directly upload folder structure.\n\n**Note**: Please specify either a local upload path or a folder structure JSON path, not both.\n\n### Define script parameters\n\nThere are 3 ways to pass parameters:\n* Use hardcoded value in script:\n\nPlease update all needed parameters in the script [here](/examples/User%20Creation%20%26%20Provisioning/Users_Create_Provision.ps1#L19-L38) before running.\n\n* Run script with parameters:\n\nYou can also specify parameters while run the command, for example:\n```\nPS > ./Users_Create_Provision.ps1 -EmployeeList ./Employees_1.csv `\n\t-FolderStructureJSONPath ./Folder_Structure.json `\n\t-PersonalFolderSlug \"Personal Folder\" `\n\t-PersonalFolderParentID 123456789\n\nStarting User Creation & Provisioning script...\n```\n\n* If you don't specify parameters, the script will prompt you to enter it.\n\n```\nPS > ./Users_Create_Provision.ps1\nPlease enter the path to the employee list CSV file:\n./Employees_1.csv\nPlease enter the path to the folder structure JSON file or the local upload path:\nFolder_Structure.json\nFolder structure JSON path set to: Folder_Structure.json\nPlease enter the ID of the parent folder for the personal folders to be created in:\n1234567689\nStarting User Creation & Provisioning script...\n```\n\n## Run the script\nNow all you need to do is run the script. Change the directory to the folder containing the script. In this example, it is the `User Creation & Provisioning` folder.\n```\nrvb@lab:~/box-cli/examples/User Creation & Provisioning$ pwsh\nPowerShell 7.2.4\nCopyright (c) Microsoft Corporation.\n\nhttps://aka.ms/powershell\nType 'help' to get help.\n\nPS /home/rvb/box-cli/examples/User Creation & Provisioning>\n```\n\nRun the script: \n```bash\n./Users_Create_Provision.ps1\n```\n\nWhen all parameters are defined, you will see following output to confirm the script started:\n```\nPS /home/rvb/box-cli/examples/User Creation & Provisioning> ./Users_Create_Provision.ps1\nStarting User Creation & Provisioning script...\n```\n\n## Logging\nLogs are stored in a `logs` folder located in the main folder. You have access to these log files:\n\n* `Users_Create_Provision_all.txt` that contains all log entries.\n* `Users_Create_Provision_errors.txt` that contains only errors.\n\n## Disclaimer\nThis project is a collection of open source examples and should not be treated as an officially supported product. Use at your own risk and as a source of example how to use Box CLI.\n\n[oauth-guide]: https://developer.box.com/guides/cli/quick-start/\n"
  },
  {
    "path": "examples/User Creation & Provisioning/Users_Create_Provision.ps1",
    "content": "#APP SETUP\n#README: This powershell script will use the Box CLI to build and create a user (admin or service account) owned \"Personal\" folder structure, create managed users in bulk, and provision the new users by collaborating them as viewer and uploaders into their newly created personal folder structure.\n\n#APPLICATION ACCESS LEVEL (FOR JWT APPS): App + Enterprise Access Selected\n#FOR Oauth 2.0 APPS: User configured with CLI must be admin or co-admin\n#APPLICATION SCOPES: Read & Write all folders stored in Box, Manage users, & Make API calls using the as-user header\n\n########################################################################################\n\n# Example of configuration\n# param (\n#     [string]$EmployeeList = \"./Employees_5.csv\",\n#     [string]$FolderStructureJSONPath = \"./Folder_Structure.json\",\n#     [string]$LocalUploadPath = \"./PersonalLocalUpload\",\n#     [string]$PersonalFolderSlug = \"Personal Folder\",\n#     [string]$PersonalFolderParentID = \"123456789\"\n# )\n\nparam (\n    # Set Employee List CSV Path\n    # firstname, lastname, email, username\n    # NOTE 1 - EMAILS MUST BE UNIQUE ACROSS ALL OF BOX - CANNOT CREATE EMAILS USED PREVIOUSLY\n    # NOTE 2 - USERNAME MUST BE UNIQUE ACROSS YOUR BOX INSTANCE. - THIS IS USED FOR THE PERSONAL FOLDER NAME \n    [string]$EmployeeList = \"\",\n\n    # Personal Folder Structure: Set either path build off JSON or directly upload a local folder\n    [string]$FolderStructureJSONPath = \"\",\n    [string]$LocalUploadPath = \"\",\n    \n    # Ending slug of folder that will be used in creating personal folders for new users. Value will get concatenated with username\n    # If username is RSMITH, the boarding folder name would be RSMITH Personal Folder\n    [string]$PersonalFolderSlug = \"Personal Folder\",\n\n    # ID of parent folder for created personal folders to be created in\n    # This folder should be created before running the script the first time.\n    # It is not advised to make this value 0, as this will create individual Personal folders in root of the account you set up the cli with\n    [string]$PersonalFolderParentID = \"\"\n)\n\n#############################################################################\n\n# Get current script file name\nFunction Get-Script-Name() {\n    $filename = $MyInvocation.ScriptName | Split-Path -Leaf\n    if ($filename -match \".\") {\n        $filename = $filename.Substring(0, $filename.LastIndexOf(\".\"))\n    }\n\n    return $filename\n}\n\n# Function to write to logs\nFunction Write-Log { param ([string]$message, [string]$errorMessage = $null, [Exception]$exception = $null, [string]$output = $false, [string]$color = \"Green\")\n\n    # Define log level - Can be \"errors\" or \"all\"\n    $logLevel = \"all\"\n\n    # Create logs directory if it doesn't exist\n    if (-not (Test-Path \".\\logs\")) {\n        New-Item -Path . -Name \"logs\" -ItemType 'directory' > $null\n    }\n\n    $dateTime = Get-Date\n\n    # Set log filename to the name of the script\n    $logFilename = Get-Script-Name\n    $debugErrorFile = \".\\logs\\\" + $logFilename + \"_errors.txt\"\n    $debugAllFile = \".\\logs\\\" + $logFilename + \"_all.txt\"\n\n    if ($exception -or $errorMessage) {\n        $severity = \"ERROR\"\n    } else {\n        $severity = \"INFO\"\n    }\n\n    if ($exception.Response) {\n        $result = $exception.Response.GetResponseStream()\n        $reader = New-Object System.IO.StreamReader($result)\n        $reader.BaseStream.Position = 0\n        $reader.DiscardBufferedData()\n        $responseBody = $reader.ReadToEnd();\n    }\n\n    $logMessage = ($severity + \"`t\")\n    $logMessage += ($dateTime)\n    $logMessage += (\"`t\" + $message + \"`t\")\n\n    if ($exception) {\n        $logMessage += ($exception.Message + \"`t\")\n    }\n\n    if ($errorMessage) {\n        $logMessage += ($errorMessage + \"`t\")\n    }\n\n    if ($responseBody) {\n        $logMessage += (\"Box responded with: \" + $responseBody + \"`t\")\n    }\n\n    if ($output -eq \"true\") {\n        Write-Host $message -ForegroundColor $color\n    }\n\n    if ($logLevel -eq \"all\") {\n        $logMessage | Add-Content $debugAllFile\n\n        if ($severity -eq \"ERROR\") {\n            $logMessage | Add-Content $debugErrorFile\n        }\n    } else {\n        if ($severity -eq \"ERROR\") {\n            $logMessage | Add-Content $debugErrorFile\n        }\n    }\n}\n\n# This class is used for setting/restoring analytics client header when running this script\nclass AnalyticsClientManager {\n    [string]$TemporaryAnalyticsClientName\n    [string]$OriginalAnalyticsClientName\n    [bool]$IsOriginalAnalyticsClientEnabled\n\n    AnalyticsClientManager([string]$temporaryAnalyticsClientName) {\n        $this.TemporaryAnalyticsClientName = \"box_sample_scripts $($temporaryAnalyticsClientName)\"\n    }\n\n    [bool] IsAnalyticsClientSupported() {\n        return \"$(box configure:settings --help)\" -like \"*--analytics-client-name*--json*\"\n    }\n\n    [void] StoreOriginalSettings() {\n        $SettingsContent = \"$(box configure:settings --json)\" | ConvertFrom-Json\n\n        $this.OriginalAnalyticsClientName = $SettingsContent.AnalyticsClient.Name\n        if (!$this.OriginalAnalyticsClientName) {\n            $this.OriginalAnalyticsClientName = \"cli\"\n        }\n\n        if($SettingsContent.EnableanalyticsClient) {\n            $this.IsOriginalAnalyticsClientEnabled = $true\n        } else {\n            $this.IsOriginalAnalyticsClientEnabled = $false\n        }\n\n        Write-Log \"Stored original analytics client settings, name: $($this.OriginalAnalyticsClientName), enabled: $($this.IsOriginalAnalyticsClientEnabled).\" -output false\n    }\n\n    [void] RestoreOriginalSettings() {\n        if ($this.IsOriginalAnalyticsClientEnabled) {\n            $RestoreAnalyticsClientEnablementState = \"--enable-analytics-client\"\n        } else {\n            $RestoreAnalyticsClientEnablementState = \"--no-enable-analytics-client\"\n        }\n\n        \"$(box configure:settings $RestoreAnalyticsClientEnablementState --analytics-client-name=$($this.OriginalAnalyticsClientName))\"\n        Write-Log \"Restored original analytics client settings, name: $($this.OriginalAnalyticsClientName), enabled: $($this.IsOriginalAnalyticsClientEnabled).\" -output false\n    }\n\n    [void] SetScriptAnalyticsClient() {\n        if ($this.IsAnalyticsClientSupported()) {\n            $this.StoreOriginalSettings()\n\n            \"$(box configure:settings --enable-analytics-client --analytics-client-name=$($this.TemporaryAnalyticsClientName))\"\n            Write-Log \"Set temporarily analytics client settings, name: $($this.TemporaryAnalyticsClientName), enabled: true.\" -output false\n        }\n    }\n\n    [void] UnsetScriptAnalyticsClients() {\n        if ($this.IsAnalyticsClientSupported()) {\n            $this.RestoreOriginalSettings()\n        }\n    }\n}\n\n#############################################################################\n\nif ($LocalUploadPath -and $FolderStructureJSONPath) {\n    Write-Log \"Please specify either a local upload path or a folder structure JSON path, not both.\" -output true -color Red\n    exit\n}\n\n# Prompt for params if some are missing\nif (-not $EmployeeList) {\n    Write-Log \"Please enter the path to the employee list CSV file:\" -output true -color Yellow\n    $EmployeeList = Read-Host\n}\nif (-not $FolderStructureJSONPath -and -not $LocalUploadPath) {\n    Write-Log \"Please enter the path to the folder structure JSON file or the local upload path:\"  -output true -color Yellow\n    $UserInput = Read-Host\n    if (Test-Path $UserInput) {\n        if ((Get-Item $UserInput) -is [System.IO.DirectoryInfo]) {\n            $LocalUploadPath = $UserInput\n            Write-Log \"Local upload path set to: $LocalUploadPath\" -output true -color Green\n        } else {\n            $FolderStructureJSONPath = $UserInput\n            Write-Log \"Folder structure JSON path set to: $FolderStructureJSONPath\" -output true -color Green\n        }\n    } else {\n        Write-Log \"Path does not exist.\" -errorMessage \"Path $UserInput does not exist\" -output true -color Red\n        exit\n    }\n}\nif (-not $PersonalFolderSlug) {\n    Write-Log \"Please enter the ending slug for each personal folder:\" -output true -color Yellow\n    $PersonalFolderSlug = Read-Host\n}\nif (-not $PersonalFolderParentID) {\n    Write-Log \"Please enter the ID of the folder where you would like to create the personal folders:\" -output true -color Yellow\n    $PersonalFolderParentID = Read-Host\n}\n\nif (-not ($EmployeeList -and ($FolderStructureJSONPath -or $LocalUploadPath) -and $PersonalFolderParentID) -or (-not $PersonalFolderSlug)) {\n    Write-Log \"Missing required parameters.\" -errorMessage \"Missing required parameters\" -output true -color Red\n    exit\n}\n\n#############################################################################\n\n$script:PersonalFolderID = $null\n\n#  User Creation & Perfonal Folder Provisioning\nFunction Start-Users-Provisoning-Creation-Script {\n    Write-Log \"Starting User Creation & Personal Folder Provisioning script...\" -output true\n\n    try {\n        # Get employees json file and convert from CSV to an array of objects\n        $Employees = Import-Csv $EmployeeList\n        Write-Log $Employees -output true\n    }\n    catch {\n        Write-Log \"Failed to load mock employee data. Exits script.\" -errorMessage \"Invalid input data.\" -output true -color Red\n        break\n    }\n\n    try {\n        #Create Managed Users and Provision Personal Folder\n        New-Provision-Managed-User\n        Write-Log \"Users and Folders Created Successfully\" -output true\n    }\n    catch {\n        Write-Log \"Failed to create managed users. Exists Script.\" -errorMessage \"Something went wrong\" -output true -color Red\n    }\n\n}\n\n# Create new managed users and add them as collaborators to created folders\nFunction New-Provision-Managed-User {\n    ForEach ($Employee in $Employees) {\n        Write-Log \"Creating employee Managed User account with first name: $($Employee.firstName), last name: $($Employee.lastName), email: $($Employee.email)\" -output True\n\n        # Create Managed User\n        try {\n            $CreatedManagedUserResp = (box users:create \"$($Employee.firstName) $($Employee.lastName)\" $Employee.email --json 2>&1)\n            $ManagedUserID = $CreatedManagedUserResp | ConvertFrom-Json | ForEach-Object { $_.id }\n            Write-Log \"Created Managed user for email: $($Employee.email) where ID: $($ManagedUserID).\" -output True\n        }\n        catch {\n            Write-Log \"Failed to create Managed User for email: $($Employee.email). Skipping this user. See log for details.\" -errorMessage $CreatedManagedUserResp -output true -color Red\n            continue\n        }\n        \n        #Create Folders\n        try {\n            # If a username is not supplied in the csv, the email address is used instead\n            if (-not $($Employee.username)){\n                $script:PersonalFolderName = $($Employee.email) + \"'s \" + $PersonalFolderSlug\n            } else {\n                $script:PersonalFolderName = $($Employee.username) + \"'s \" + $PersonalFolderSlug\n            }\n            Write-Log \"Personal Folder Name: $PersonalFolderName \" -output True\n            if ($FolderStructureJSONPath) {\n                # Create Folder Structure from JSON\n                New-Folder-Structure\n            }\n            elseif ($LocalUploadPath) {\n                # OR directly upload Folder structure to current user's root folder from local directory\n                $UploadedFoldersResp = box folders:upload $LocalUploadPath --parent-folder=$PersonalFolderParentID --folder-name=$script:PersonalFolderName --json 2>&1\n                $script:PersonalFolderID = $UploadedFoldersResp | ConvertFrom-Json | ForEach-Object { $_.id }\n            }\n            Write-Log \"Uploaded local folder structure to current user's folder with ID $($script:PersonalFolderID) where parent ID: $PersonalFolderParentID.\" -output true\n        }\n        catch {\n            Write-Log \"Failed to upload local folder structure to parent folder with ID $PersonalFolderParentID. Exits script.\" -errorMessage $UploadedFoldersResp -output true -color Red\n            break\n        }\n\n        # Collaborate New Managed User to Folder Structure owned by current user\n        try {\n            $CollaboratedResp = box folders:collaborations:add $script:PersonalFolderID --role=viewer_uploader --user-id=$ManagedUserID --json 2>&1\n            $CollaboratedResp | ConvertFrom-Json | Out-Null\n            Write-Log \"Collaborated Managed User $($Employee.firstName) $($Employee.lastName) to current user's indicated folder for provisioning with ID: $script:PersonalFolderID.\" -output True\n        }\n        catch {\n            Write-Log \"Failed to create collaboration for user $($Employee.firstName) $($Employee.lastName) with ID: $ManagedUserID, to folder ID: $script:PersonalFolderID. See log for details.\" -errorMessage $CollaboratedResp -output true -color Red\n            continue\n        }\n    }\n}\n\n# Create folder sturcture form JSON file\nFunction New-Folder-Structure {\n    # Extract folder structure from json\n    Write-Log \"Extracting folder structure\" -output True\n    try {\n        $FolderStructure = Get-Content -Raw -Path $FolderStructureJSONPath | ConvertFrom-Json\n    }\n    catch {\n        Write-Log \"Error reading '$FolderStructureJSONPath'. Exits script.\". -errorMessage \"Invalid input data.\"  -output True -color Red\n        break\n    }\n\n    # Create Personal Root folder\n    try {\n        $CreatedPersonalFolderResp = box folders:create \"$PersonalFolderParentID\" \"$script:PersonalFolderName\" --json 2>&1\n        $script:PersonalFolderID = $CreatedPersonalFolderResp | ConvertFrom-Json | ForEach-Object { $_.id }\n        Write-Log \"Created a user owned '$PersonalFolderSlug' folder with id: $($script:PersonalFolderID).\" -output True\n    }\n    catch {\n        Write-Log \"Failed to create '$script:PersonalFolderName' folder. See log for details. Exits script.\". -errorMessage $CreatedPersonalFolderResp -output True -color Red\n        break\n    }\n\n    # Create all folders structure from json file, where $PersonalFolderSlug is the parent\n    New-Subfolders-Recursively \"$script:PersonalFolderID\" \"$script:PersonalFolderName\" $FolderStructure\n}\n\n# Creates folders structure\nFunction New-Subfolders-Recursively {\n    Param\n    (\n         [Parameter(Mandatory=$true, Position=0)]\n         [string] $ParentFolderId,\n         [Parameter(Mandatory=$true, Position=1)]\n         [string] $ParentFolderName,\n         [Parameter(Mandatory=$true, Position=2)]\n         [System.Object[]] $Children\n    )\n\n    ForEach ($child in $Children) {\n        try {\n            $CreatedChildFolderResp = box folders:create \"$($ParentFolderId)\" \"$($child.name)\" --fields=\"id,name\" --json 2>&1\n            $CreatedChildFolder = $CreatedChildFolderResp | ConvertFrom-Json\n            Write-Log \"Created subfolder '$($child.name)' with id: $($CreatedChildFolder.id) under '$ParentFolderName' (ID: $ParentFolderId) folder.\" -output True\n\n            if ($child.children -and $child.children.Length -gt 0) {\n                New-Subfolders-Recursively \"$($CreatedChildFolder.id)\" \"$($child.name)\" $($child.children)\n            }\n        }\n        catch {\n            Write-Log \"Failed to create subfolder '$($child.name)' under '$ParentFolderName' (ID: $ParentFolderId) folder. See log for details.\". -errorMessage $CreatedChildFolderResp -output True -color Red\n            continue\n        }\n    }\n}\n\n# Start function\nFunction Start-Script {\n    try {\n        $AnalyticsClientManager = [AnalyticsClientManager]::new($(Get-Script-Name).ToLower())\n        $AnalyticsClientManager.SetScriptAnalyticsClient()\n\n        Start-Users-Provisoning-Creation-Script\n    } finally {\n        $AnalyticsClientManager.UnsetScriptAnalyticsClients()\n    }\n}\n\n# Ensure console output is UTF-8 so non-ASCII characters from Box CLI render correctly\n[Console]::OutputEncoding = [System.Text.Encoding]::UTF8\nStart-Script\n"
  },
  {
    "path": "examples/User Deprovisioning/Employees_to_delete.csv",
    "content": "﻿name,email\nManaged User 1,ManagedUser1@test.com\nManaged User 2,ManagedUser2@test.com\nManaged User 3,ManagedUser3@test.com\nManaged User 4,ManagedUser4@test.com\nManaged User 5,ManagedUser5@test.com\n"
  },
  {
    "path": "examples/User Deprovisioning/README.md",
    "content": "# Deprovision & Delete Users Automation\nThis Box CLI script deprovision a list of users by first transfering user content to another user's root folder under \"Employee Archive\" before deleting that user.\n\n> For every user, script makes 7 API calls to archive their content and delete the account.\n\n**For detailed script overview, please follow [this guide](https://developer.box.com/guides/cli/scripts/deprovision-users/).**\n\n## Setup Pre-Requisites\n1. Clone this github repo or download files from the `/examples` directory.\n   ```bash\n   git clone https://github.com/box/boxcli.git\n   ```\n2. Install PowerShell or .Net core.\n   > If you encounter issues make sure you install both dotnet core and PowerShell\n    1. For MacOS & Linux, Install the latest version of [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/install/installing-powershell?view=powershell-7.2).\n    2. For Windows, Install the latest version of [dotnet core](https://dotnet.microsoft.com/download).\n    \n3. Test PowerShell by running the `pwsh` command in your terminal.\n   \n   ```bash\n   pwsh\n   ```\n   \n   ```bash\n   mikechen@mbp create-users-automation % pwsh\n   PowerShell 7.2.1\n   Copyright (c) Microsoft Corporation.\n   \n   https://aka.ms/powershell\n   Type 'help' to get help.\n   \n   PS /Users/mikechen>\n   ```\n\n4. Create an OAuth Application using the [CLI Setup Quick Start][oauth-guide].\n\n## Configure the script\n### Update the list of employees for deletion\n\nThe header row should look like the below:\n\n   ```bash\n   name, email\n   ```\n\n   where:\n   \n   * `name` is the name of the user in Box. \n   * `email` is the primary email address of the user in Box.\n\nFor example, update the [Employees_to_delete.csv](/examples/User%20Deprovisioning/Employees_to_delete.csv) with the following data:\n\n   ```bash\n   Managed,User 1,ManagedUser1@test.com,manageduser1\n   Managed,User 2,ManagedUser2@test.com,manageduser2\n   Managed,User 3,ManagedUser3@test.com,manageduser3\n   ```\n\n### List of parameters\n\n   |`Parameter`| `Description`| `Required` | `Default Value` |\n   |-----------|--------------|------------|-----------------|\n   |`EmployeeList`|  Path to Employee List CSV with employees to be deleted. | Yes | - |\n   |`SkipTransferContent`| Set this flag to skip transfer of user content before deletion when running the script. Otherwise user's content will be transferred. | No | `False` |\n   |`NewFilesOwnerID`|  The ID of the user to transfer files to before deleting the user. If not specified, the script will prompt to input in the interactive mode, or use the current authenticated user ID to receive the content.| No | If not specified, the script will prompt to input in the interactive mode, or use the current authenticated user ID. |\n   |`EmployeeArchiveFolderName`|The name of a folder, where users' content will be moved to if `SkipTransferContent` is set to `False`. If a folder with this name already exists in the user's `NewFilesOwnerID` root folder, it will be used. Otherwise, a new one will be created.|Yes|`Employee Archive`|\n   |`DryRun`|A flag that determines the script should be run in a mode, where no delete/create/update calls will be made, only read ones. |No|`False`|\n\n\n### Define script parameters\n\nYou can the following options to pass parameters.\n\n* Use hardcoded value in script.\n\n    To use this option, update all required parameters listed in the [script parameters section][parameters] before running.\n\n* Run script with parameters.\n\n  You can specify parameters while providing the command. For example:\n\n     ```bash\n      PS > ./Users_Deprovision.ps1 -EmployeeList ./Employees_to_delete.csv `\n      -NewFilesOwnerID  123456789\n      -EmployeeArchiveFolderName \"Employee Archive\"\n     ```\n\n  or\n\n     ```bash\n      PS > ./Users_Deprovision.ps1 -EmployeeList ./Employees_to_delete.csv `\n      -SkipTransferContent\n     ```\n\n  If you don't specify parameters, the script will prompt you to enter it.\n\n     ```bash\n      PS > ./Users_Deprovision.ps1\n      Please enter the path to the employee list CSV file:\n      ./Employees_to_delete.csv\n      Please specify the user ID of the user who will own the files of the users being deprovisioned.\n      Press Enter if you want to use the current user as the new owner.\n      User ID: 1234567689\n      Starting User Deprovisioning script...\n     ```\n\n## Run the script\nNow all you need to do is run the script. Change the directory to the folder containing the script. In this example, it is the `User Deprovisioning` folder.\n\n```bash\nrvb@lab:~/box-cli/examples/User Deprovisioning$ pwsh\nPowerShell 7.2.4\nCopyright (c) Microsoft Corporation.\n\nhttps://aka.ms/powershell\nType 'help' to get help.\n\nPS /home/rvb/box-cli/examples/User Deprovisioning>\n```\n\nRun the script:\n\n```bash\n./Users_Deprovision.ps1\n```\n\nWhen all parameters are defined, you will see following output to confirm the script started:\n\n```bash\nPS /home/rvb/box-cli/examples/User Deprovisioning> ./Users_Deprovision.ps1\nStarting User Deprovisioning script...\n```\n\n## Logging\nLogs are stored in a `logs` folder located in the main folder. You have access to these log files:\n\n* `Users_Deprovision_all.txt` that contains all log entries.\n* `Users_Deprovision_errors.txt` that contains only errors.\n\n## Disclaimer\nThis project is a collection of open source examples and should not be treated as an officially supported product. Use at your own risk and as a source of example how to use Box CLI.\n\n[oauth-guide]: https://developer.box.com/guides/cli/quick-start/\n"
  },
  {
    "path": "examples/User Deprovisioning/Users_Deprovision.ps1",
    "content": "#APP SETUP\n#README: This powershell script will use the Box CLI to deprovision a list of users by first transferring user content to the current admin user's root folder before deleting that user.\n\n#APPLICATION ACCESS LEVEL (FOR JWT APPS): App + Enterprise Access\n#APPLICATION SCOPES: Read & Write all folders stored in Box, Manage users, & Make API calls using the as-user header\n########################################################################################\n\n# Example of configuration\n# param (\n#     [string]$EmployeeList = \"./Employees_to_delete.csv\",\n#     [switch]$SkipTransferContent = $false,\n#     [string]$NewFilesOwnerID = \"123456789\",\n#     [string]$EmployeeArchiveFolderName = \"Employee Archive\",\n#     [switch]$DryRun = $false\n# )\n\nparam (\n    # Set Employee List CSV Path with employees to be deleted.\n    # The file should have two columns: name,email.\n    [string]$EmployeeList = \"\",\n\n    # Skip transfering user content before deleting to the user with ID -> $NewFilesOwnerID.\n    [switch]$SkipTransferContent = $false,\n\n    # The ID of the user to transfer files to before deleting the user.\n     # If not specified, current user will be used.\n    [string]$NewFilesOwnerID = \"\",\n\n    # The name of a folder, where users' content will be moved to if $SkipTransferContent is set to $false(default value).\n    # If a folder with this name already exists in the user's $NewFilesOwnerID root folder, it will be used. Otherwise, a new one will be created.\n    # NOTE - If you want to be promt to enter archive folder name, set this value to an empty string.\n    [string]$EmployeeArchiveFolderName = \"Employee Archive\",\n\n     # If enabled, then no delete/create/update calls will be made, only read ones\n    [switch]$DryRun = $false\n)\n\n########################################################################################\n\n# Get current script file name\nFunction Get-Script-Name() {\n    $filename = $MyInvocation.ScriptName | Split-Path -Leaf\n    if ($filename -match \".\") {\n        $filename = $filename.Substring(0, $filename.LastIndexOf(\".\"))\n    }\n\n    return $filename\n}\n\n# Function to write to logs\nFunction Write-Log { param ([string]$message, [string]$errorMessage = $null, [Exception]$exception = $null, [string]$output = $false, [string]$color = \"Green\")\n\n    # Define log level - Can be \"errors\" or \"all\"\n    $logLevel = \"all\"\n\n    # Create logs directory if it doesn't exist\n    if (-not (Test-Path \".\\logs\")) {\n        New-Item -Path . -Name \"logs\" -ItemType 'directory' > $null\n    }\n\n    $dateTime = Get-Date\n\n    # Set log filename to the name of the script\n    $logFilename = Get-Script-Name\n    $debugErrorFile = \".\\logs\\\" + $logFilename + \"_errors.txt\"\n    $debugAllFile = \".\\logs\\\" + $logFilename + \"_all.txt\"\n\n    if ($exception -or $errorMessage) {\n        $severity = \"ERROR\"\n    } else {\n        $severity = \"INFO\"\n    }\n\n    if ($exception.Response) {\n        $result = $exception.Response.GetResponseStream()\n        $reader = New-Object System.IO.StreamReader($result)\n        $reader.BaseStream.Position = 0\n        $reader.DiscardBufferedData()\n        $responseBody = $reader.ReadToEnd();\n    }\n\n    $logMessage = ($severity + \"`t\")\n    $logMessage += ($dateTime)\n    $logMessage += (\"`t\" + $message + \"`t\")\n\n    if ($exception) {\n        $logMessage += ($exception.Message + \"`t\")\n    }\n\n    if ($errorMessage) {\n        $logMessage += ($errorMessage + \"`t\")\n    }\n\n    if ($responseBody) {\n        $logMessage += (\"Box responded with: \" + $responseBody + \"`t\")\n    }\n\n    if ($output -eq \"true\") {\n        Write-Host $message -ForegroundColor $color\n    }\n\n    if ($logLevel -eq \"all\") {\n        $logMessage | Add-Content $debugAllFile\n\n        if ($severity -eq \"ERROR\") {\n            $logMessage | Add-Content $debugErrorFile\n        }\n    } else {\n        if ($severity -eq \"ERROR\") {\n            $logMessage | Add-Content $debugErrorFile\n        }\n    }\n}\n\n# This class is used for setting/restoring analytics client header when running this script\nclass AnalyticsClientManager {\n    [string]$TemporaryAnalyticsClientName\n    [string]$OriginalAnalyticsClientName\n    [bool]$IsOriginalAnalyticsClientEnabled\n\n    AnalyticsClientManager([string]$temporaryAnalyticsClientName) {\n        $this.TemporaryAnalyticsClientName = \"box_sample_scripts $($temporaryAnalyticsClientName)\"\n    }\n\n    [bool] IsAnalyticsClientSupported() {\n        return \"$(box  configure:settings --help)\" -like \"*--analytics-client-name*--json*\"\n    }\n\n    [void] StoreOriginalSettings() {\n        $SettingsContent = \"$(box configure:settings --json)\" | ConvertFrom-Json\n\n        $this.OriginalAnalyticsClientName = $SettingsContent.AnalyticsClient.Name\n        if (!$this.OriginalAnalyticsClientName) {\n            $this.OriginalAnalyticsClientName = \"cli\"\n        }\n\n        if($SettingsContent.EnableanalyticsClient) {\n            $this.IsOriginalAnalyticsClientEnabled = $true\n        } else {\n            $this.IsOriginalAnalyticsClientEnabled = $false\n        }\n\n        Write-Log \"Stored original analytics client settings, name: $($this.OriginalAnalyticsClientName), enabled: $($this.IsOriginalAnalyticsClientEnabled).\" -output false\n    }\n\n    [void] RestoreOriginalSettings() {\n        if ($this.IsOriginalAnalyticsClientEnabled) {\n            $RestoreAnalyticsClientEnablementState = \"--enable-analytics-client\"\n        } else {\n            $RestoreAnalyticsClientEnablementState = \"--no-enable-analytics-client\"\n        }\n\n        \"$(box configure:settings $RestoreAnalyticsClientEnablementState --analytics-client-name=$($this.OriginalAnalyticsClientName))\"\n        Write-Log \"Restored original analytics client settings, name: $($this.OriginalAnalyticsClientName), enabled: $($this.IsOriginalAnalyticsClientEnabled).\" -output false\n    }\n\n    [void] SetScriptAnalyticsClient() {\n        if ($this.IsAnalyticsClientSupported()) {\n            $this.StoreOriginalSettings()\n\n            \"$(box configure:settings --enable-analytics-client --analytics-client-name=$($this.TemporaryAnalyticsClientName))\"\n            Write-Log \"Set temporarily analytics client settings, name: $($this.TemporaryAnalyticsClientName), enabled: true.\" -output false\n        }\n    }\n\n    [void] UnsetScriptAnalyticsClients() {\n        if ($this.IsAnalyticsClientSupported()) {\n            $this.RestoreOriginalSettings()\n        }\n    }\n}\n\n# Function to check if current script is running under non-interactive mode\nfunction IsInteractiveShell {\n    # Test each Arg for match of abbreviated '-NonInteractive' command.\n    $NonInteractive = [Environment]::GetCommandLineArgs() | Where-Object{ $_ -like '-NonI*' }\n\n    if ([Environment]::UserInteractive -and -not $NonInteractive) {\n        # We are in an interactive shell.\n        return $true\n    }\n\n    return $false\n}\n\n#############################################################################\n\n# Prompt for params if they are missing\nif (IsInteractiveShell) {\n    if (-not $EmployeeList) {\n        Write-Log \"Please enter the path to the employee list CSV file:\" -output true -color Yellow\n        $EmployeeList = Read-Host\n    }\n\n    if (-not $SkipTransferContent) {\n        if (-not $NewFilesOwnerID) {\n            Write-Log \"Please specify the user ID of the user who will own the files of the users being deprovisioned.\" -output true -color Yellow\n            Write-Log \"Press Enter if you want to use the current user as the new owner.\" -output true -color Yellow\n            $NewFilesOwnerID = Read-Host \"User ID\"\n        }\n\n        if (-not $EmployeeArchiveFolderName) {\n            Write-Log \"Please enter the archive folder name where users' content will be moved to:\" -output true -color Yellow\n            $EmployeeArchiveFolderName = Read-Host\n        }\n    }\n}\n\nif (-not $EmployeeList -or (-not $SkipTransferContent -and (-not $EmployeeArchiveFolderName))) {\n    Write-Log \"Missing required parameters.\" -errorMessage \"Missing required parameters\" -output true -color Red\n    exit\n}\n\n#############################################################################\n\n$EmployeeArchiveFolderID = $null\n\n# Deprovision users\nFunction Start-Deprovisioning-Script {\n    if ($DryRun) {\n        Write-Log \"Starting User Deprovisioning script in DryRun mode...\" -output true\n    } else {\n        Write-Log \"Starting User Deprovisioning script...\" -output true\n    }\n\n    # Get employees json file and convert from CSV to an array of objects\n    try {\n        $Employees = Import-Csv $EmployeeList\n        Write-Log \"Importing csv of users to deprovision.\" -output true\n    }\n    catch {\n        Write-Log \"Error reading employee data from CSV file $EmployeeList\" -exception $_.Exception -output true -color Red\n        break\n    }\n\n    # Create folder if need to transfer content\n    if (-not $SkipTransferContent) {\n        # Check if new file owner ID already specified\n        if ($NewFilesOwnerID) {\n            Write-Log \"New files owner ID is set to: $NewFilesOwnerID\" -output true -color Green\n        }\n\n        # Getting current user\n        $CurrentUserId = \"\"\n        try {\n            $UserResp = \"$(box users:get --json 2>&1)\"\n            $User = $UserResp | ConvertFrom-Json\n            $CurrentUserId = $User.id\n            Write-Log \"Successfully get current user: $($User.login), ID: $($User.id).\" -output true\n            Write-Log $UserResp\n        } catch {\n            Write-Log \"Could not get the current user. See log for details.\" -errorMessage $UserResp -output true -color Red\n            break\n        }\n\n        # Validate new files owner if is not current user\n        $AsUserHeader = \"\"\n        if ($NewFilesOwnerID -and ($NewFilesOwnerID -ne $CurrentUserId)) {\n            Write-Log \"Validating new files owner exists\" -output true -color Yellow\n            try {\n                $UserResp = \"$(box users:get --as-user=$NewFilesOwnerID --json 2>&1)\"\n                $User = $UserResp | ConvertFrom-Json\n                $AsUserHeader = \"--as-user=$NewFilesOwnerID\"\n                Write-Log \"Successfully validated new files owner: $($User.login), ID: $($User.id).\" -output true\n                Write-Log $UserResp\n            } catch {\n                Write-Log \"New files owner does not exists. See log for details.\" -errorMessage $UserResp -output true -color Red\n                break\n            }\n        }\n\n        # Use current user and new files owner if not specified\n        if (!$NewFilesOwnerID) {\n            Write-Log \"Using current user as new files owner\" -output true -color Yellow\n            $NewFilesOwnerID = $CurrentUserId\n        }\n\n        # Create a \"Employee Archive\" folder in User's Root directory if one does not already exist\n        # List root folder contents\n        try {\n            $RootFolderResp = \"$(box folders:items 0 --sort=name --direction=ASC $AsUserHeader --json 2>&1)\"\n            $RootFolder = $RootFolderResp | ConvertFrom-Json\n        } catch {\n            Write-Log \"Could not get root directory for current user (ID: $NewFilesOwnerID). See log for details. \" -errorMessage $RootFolderResp -output true -color Red\n            break\n        }\n\n        # Check if \"Employee Archive\" folder already exists\n        ForEach($FolderItem in $RootFolder) {\n            if($FolderItem.name -eq $EmployeeArchiveFolderName) {\n                $EmployeeArchiveFolderID = $FolderItem.id\n                Write-Log \"'$EmployeeArchiveFolderName' folder already exists with folder ID: $($EmployeeArchiveFolderID).\" -output true\n                break\n            }\n        }\n\n        # Create new \"Employee Archive\" folder if it doesn't exist\n        if($null -eq $EmployeeArchiveFolderID) {\n            if(!$DryRun) {\n                try {\n                    $EmployeeArchiveFolderResp = \"$(box folders:create 0 \"$EmployeeArchiveFolderName\" $AsUserHeader --fields=\"id\" --json 2>&1)\"\n                    $EmployeeArchiveFolderID = $EmployeeArchiveFolderResp | ConvertFrom-Json | ForEach-Object { $_.id }\n                    Write-Log \"Successfully created new '$EmployeeArchiveFolderName' root folder with ID: $($EmployeeArchiveFolderID).\" -output true\n                    Write-Log $EmployeeArchiveFolderResp\n                } catch {\n                    Write-Log \"Could not create new '$EmployeeArchiveFolderName' root folder. See log for details.\" -errorMessage $EmployeeArchiveFolderResp -output true -color Red\n                    break\n                }\n            } else {\n                Write-Log \"`\"DryRun`\" mode is enabled. Script would have created new '$EmployeeArchiveFolderName' root folder.\" -output true\n            }\n        }\n    }\n\n    # Search for employee ID\n    ForEach($Employee in $Employees) {\n\n        # Check if user exists and get user ID\n        try {\n            $FoundEmployeeResp = \"$(box users:search $Employee.email --json 2>&1)\"\n            $FoundEmployee = $FoundEmployeeResp | ConvertFrom-Json\n\n            if (($FoundEmployee.Length -eq 0) -or $($FoundEmployee.total_count) -eq 0) {\n                Write-Log \"No user found for email: $($Employee.email). Skipping this employee.\" -output true -color Yellow\n                continue\n            } elseif (($FoundEmployee.Length -gt 1) -or $($FoundEmployee.total_count) -gt 1) {\n                Write-Log \"Multiple matching users found for email: $($Employee.email). Skipping this employee.\" -output true -color Yellow\n                Write-Log $FoundEmployeeResp\n                continue\n            } else {\n                $FoundEmployeeID = $FoundEmployee.id\n                Write-Log \"Found employee $($FoundEmployee.name) with ID: $FoundEmployeeID for email: $($Employee.email).\" -output true\n                Write-Log $FoundEmployeeResp\n            }\n        } catch {\n            Write-Log \"Skipping this employee. Could not find user for email: $($Employee.email). See log for details.\" -errorMessage $FoundEmployeeResp -output true -color Red\n            continue\n        }\n\n        if(!$SkipTransferContent) {\n            if(!$DryRun) {\n                # Transfer users content to current user's root folder before deleting user\n                Write-Log \"Transferring $($FoundEmployee.name) content over to current user's Root folder with name \"\"$($FoundEmployee.login) - $($FoundEmployee.name)'s Files and Folders\"\"...\" -output true\n\n                try {\n                    $NewFolderResp = \"$(box users:transfer-content $FoundEmployeeID $NewFilesOwnerID --json 2>&1)\"\n                    $NewFolder = $NewFolderResp | ConvertFrom-Json\n                    Write-Log \"Successfully transferred content to \"\"$($FoundEmployee.login) - $($FoundEmployee.name)'s Files and Folders\"\".\" -output true\n                    Write-Log $NewFolderResp\n                } catch {\n                    Write-Log \"Skipping this employee. Could not transfer $($FoundEmployee.name) content over to current user's Root folder. See log for details.\" -errorMessage $NewFolderResp -output true -color Red\n                    continue\n                }\n\n                # Move transferred folder to \"Employee Archive\" folder\n                $TransferredFolder = $NewFolder.id\n                try {\n                    $MoveFolderResp = \"$(box folders:move $TransferredFolder $EmployeeArchiveFolderID $AsUserHeader --json 2>&1)\"\n                    $MoveFolderResp | ConvertFrom-Json | Out-Null\n                    Write-Log \"Successfully moved transferred employee content $($FoundEmployee.name) with User ID: $($FoundEmployeeID) to '$EmployeeArchiveFolderName' folder with ID: $EmployeeArchiveFolderID.\" -output true\n                    Write-Log $MoveFolderResp\n                } catch {\n                    Write-Log \"Skipping this employee. Could not move transferred folder with ID: $TransferredFolder to $EmployeeArchiveFolderName folder with ID: $EmployeeArchiveFolderID. See log for details.\" -errorMessage $MoveFolderResp -output true -color Red\n                    continue\n                }\n            } else {\n                Write-Log (\"`\"DryRun`\" mode is enabled. Script would have transferred employee's content\" +`\n                \" to `\"$($FoundEmployee.login) - $($FoundEmployee.name)'s Files and Folders`\"\" +`\n                \" and then moved it to `\"$EmployeeArchiveFolderName`\" folder.\") `\n                -output true\n            }\n        }\n\n        # Delete user\n        if(!$DryRun) {\n            try {\n                $DeleteUserResp = \"$(box users:delete $FoundEmployeeID 2>&1)\"\n                if($LASTEXITCODE -eq 0) {\n                    Write-Log \"Successfully deleted employee $($FoundEmployee.name) with ID: $($FoundEmployeeID).\" -output true\n                } else {\n                    Write-Log \"Could not delete employee $($FoundEmployee.name) with ID: $($FoundEmployeeID). See log for details.\" -errorMessage $DeleteUserResp -output true -color Red\n                    continue\n                }\n            } catch {\n                Write-Log \"Could not delete employee $($FoundEmployee.name) with ID: $($FoundEmployeeID). See log for details.\" -errorMessage $DeleteUserResp -output true -color Red\n                continue\n            }\n        } else {\n            Write-Log \"`\"DryRun`\" mode is enabled. Script would have deleted employee $($FoundEmployee.name) with ID: $($FoundEmployeeID).\" -output true\n        }\n    }\n\n    Write-Log \"Complete User Deprovisioning script.\"\n}\n\n# Start function\nFunction Start-Script {\n    try {\n        $AnalyticsClientManager = [AnalyticsClientManager]::new($(Get-Script-Name).ToLower())\n        $AnalyticsClientManager.SetScriptAnalyticsClient()\n\n        Start-Deprovisioning-Script\n    } finally {\n        $AnalyticsClientManager.UnsetScriptAnalyticsClients()\n    }\n}\n\n# Ensure console output is UTF-8 so non-ASCII characters from Box CLI render correctly\n[Console]::OutputEncoding = [System.Text.Encoding]::UTF8\nStart-Script\n"
  },
  {
    "path": "package.json",
    "content": "{\n\t\"name\": \"@box/cli\",\n\t\"description\": \"Official command line interface for the Box API.\",\n\t\"keywords\": [\n\t\t\"box\",\n\t\t\"cli\",\n\t\t\"platform\",\n\t\t\"api\",\n\t\t\"upload\",\n\t\t\"download\"\n\t],\n\t\"version\": \"4.8.0\",\n\t\"author\": \"Box <oss@box.com>\",\n\t\"license\": \"Apache-2.0\",\n\t\"main\": \"src/index.js\",\n\t\"bin\": {\n\t\t\"box\": \"./bin/run\"\n\t},\n\t\"repository\": {\n\t\t\"type\": \"git\",\n\t\t\"url\": \"https://github.com/box/boxcli.git\"\n\t},\n\t\"bugs\": \"https://github.com/box/boxcli/issues\",\n\t\"dependencies\": {\n\t\t\"@discoveryjs/json-ext\": \"^0.5.7\",\n\t\t\"@oclif/core\": \"^4.8.0\",\n\t\t\"@oclif/plugin-autocomplete\": \"^3.2.39\",\n\t\t\"@oclif/plugin-help\": \"^6.2.36\",\n\t\t\"@oclif/plugin-not-found\": \"^3.2.73\",\n\t\t\"@oclif/plugin-update\": \"3.2.4\",\n\t\t\"@oclif/plugin-version\": \"^2.2.36\",\n\t\t\"@oclif/table\": \"^0.4.14\",\n\t\t\"@octokit/rest\": \"^22.0.0\",\n\t\t\"archiver\": \"^3.0.0\",\n\t\t\"box-node-sdk\": \"^4.6.0\",\n\t\t\"chalk\": \"^2.4.1\",\n\t\t\"cli-progress\": \"^2.1.0\",\n\t\t\"csv\": \"^6.3.3\",\n\t\t\"date-fns\": \"^1.29.0\",\n\t\t\"debug\": \"^4.4.0\",\n\t\t\"express\": \"^4.22.1\",\n\t\t\"fs-extra\": \"^10.1.0\",\n\t\t\"inquirer\": \"^8.2.7\",\n\t\t\"js-yaml\": \"^4.1.1\",\n\t\t\"keychain\": \"^1.5.0\",\n\t\t\"keytar\": \"^7.9.0\",\n\t\t\"lodash\": \"^4.17.13\",\n\t\t\"mkdirp\": \"^3.0.1\",\n\t\t\"nanoid\": \"^3.3.8\",\n\t\t\"open\": \"^10.1.0\",\n\t\t\"ora\": \"^5.4.1\",\n\t\t\"p-event\": \"^2.3.1\",\n\t\t\"semver\": \"^7.7.3\"\n\t},\n\t\"devDependencies\": {\n\t\t\"@oclif/test\": \"^3.2.15\",\n\t\t\"@typescript-eslint/eslint-plugin\": \"^8.17.0\",\n\t\t\"babel-eslint\": \"^10.1.0\",\n\t\t\"baseline-browser-mapping\": \"^2.9.11\",\n\t\t\"chai\": \"^4.1.2\",\n\t\t\"chai-as-promised\": \"^7.1.1\",\n\t\t\"eslint\": \"^9.38.0\",\n\t\t\"eslint-config-prettier\": \"^9\",\n\t\t\"eslint-plugin-mocha\": \"^10.5.0\",\n\t\t\"eslint-plugin-n\": \"^17.14.0\",\n\t\t\"eslint-plugin-promise\": \"^7.2.1\",\n\t\t\"eslint-plugin-unicorn\": \"^56.0.1\",\n\t\t\"generate-license-file\": \"^4.1.0\",\n\t\t\"jsonwebtoken\": \"^9.0.3\",\n\t\t\"leche\": \"^2.3.0\",\n\t\t\"mocha\": \"^11.7.5\",\n\t\t\"mockery\": \"^2.1.0\",\n\t\t\"nock\": \"^13.5.6\",\n\t\t\"nyc\": \"^17.1.0\",\n\t\t\"oclif\": \"^4.22.38\",\n\t\t\"prettier\": \"^3.6.2\",\n\t\t\"signal-exit\": \"^4.1.0\",\n\t\t\"sinon\": \"^19.0.2\",\n\t\t\"standard-version\": \"^9.5.0\",\n\t\t\"typescript\": \"^5.7.2\"\n\t},\n\t\"engines\": {\n\t\t\"node\": \">=18.0.0\"\n\t},\n\t\"files\": [\n\t\t\"/bin\",\n\t\t\"/LICENSE-THIRD-PARTY.txt\",\n\t\t\"/npm-shrinkwrap.json\",\n\t\t\"/oclif.manifest.json\",\n\t\t\"/src\"\n\t],\n\t\"oclif\": {\n\t\t\"description\": \"Official command line interface for the Box API. New here? Run 'box login -d' to sign in with your Box account in seconds. Already set up? Run 'box help' to explore all available commands.\",\n\t\t\"commands\": \"./src/commands\",\n\t\t\"bin\": \"box\",\n\t\t\"additionalHelpFlags\": [\n\t\t\t\"-h\"\n\t\t],\n\t\t\"additionalVersionFlags\": [\n\t\t\t\"-v\"\n\t\t],\n\t\t\"hooks\": {\n\t\t\t\"init\": [\n\t\t\t\t\"./src/hooks/init/verbose\"\n\t\t\t]\n\t\t},\n\t\t\"macos\": {\n\t\t\t\"identifier\": \"com.box.cli\"\n\t\t},\n\t\t\"plugins\": [\n\t\t\t\"@oclif/plugin-help\",\n\t\t\t\"@oclif/plugin-not-found\",\n\t\t\t\"@oclif/plugin-autocomplete\",\n\t\t\t\"@oclif/plugin-version\"\n\t\t],\n\t\t\"topics\": {\n\t\t\t\"autocomplete\": {\n\t\t\t\t\"description\": \"Display autocomplete installation instructions\"\n\t\t\t},\n\t\t\t\"collaborations\": {\n\t\t\t\t\"description\": \"Manage collaborations\"\n\t\t\t},\n\t\t\t\"comments\": {\n\t\t\t\t\"description\": \"Manage comments on files\"\n\t\t\t},\n\t\t\t\"configure\": {\n\t\t\t\t\"description\": \"Configure the Box CLI\"\n\t\t\t},\n\t\t\t\"configure:environments\": {\n\t\t\t\t\"description\": \"Manage your CLI environments\"\n\t\t\t},\n\t\t\t\"files\": {\n\t\t\t\t\"description\": \"Manage files\"\n\t\t\t},\n\t\t\t\"folders\": {\n\t\t\t\t\"description\": \"Manage folders\"\n\t\t\t},\n\t\t\t\"help\": {\n\t\t\t\t\"description\": \"Display help for the Box CLI\"\n\t\t\t},\n\t\t\t\"shared-links\": {\n\t\t\t\t\"description\": \"Manage shared links\"\n\t\t\t},\n\t\t\t\"tasks\": {\n\t\t\t\t\"description\": \"Manage tasks\"\n\t\t\t},\n\t\t\t\"web-links\": {\n\t\t\t\t\"description\": \"Manage web links\"\n\t\t\t}\n\t\t},\n\t\t\"update\": {\n\t\t\t\"github\": {\n\t\t\t\t\"owner\": \"box\",\n\t\t\t\t\"repo\": \"boxcli\"\n\t\t\t}\n\t\t}\n\t},\n\t\"scripts\": {\n\t\t\"test\": \"nyc mocha \\\"test/**/*.test.js\\\"\",\n\t\t\"posttest\": \"npm run lint\",\n\t\t\"lint\": \"eslint --fix ./src ./test\",\n\t\t\"clean\": \"find src/ -type d -name 'dist' -exec rm -rf {} +\",\n\t\t\"updatemd\": \"oclif readme --multi && find docs -type f -name '*.md' -exec sed -i '' 's/\\\\.ts/\\\\.js/g' {} +\",\n\t\t\"prepack\": \"npm run prettier && npm run license && oclif manifest && npm run updatemd && npm shrinkwrap && git checkout origin/main -- package-lock.json\",\n\t\t\"postpack\": \"rm -f oclif.manifest.json && rm -f npm-shrinkwrap.json\",\n\t\t\"version\": \"npm run updatemd && git add README.md && git add docs\",\n\t\t\"build\": \"oclif pack:macos && rm -rf tmp/ && oclif pack:win && rm -rf tmp/\",\n\t\t\"build:tarballs\": \"oclif pack:tarballs --no-xz --parallel\",\n\t\t\"changelog\": \"node node_modules/standard-version/bin/cli.js --skip.commit --skip.push --skip.tag --dry-run\",\n\t\t\"license\": \"generate-license-file --overwrite\",\n\t\t\"prettier\": \"prettier --write \\\"**/*.{js,json}\\\"\"\n\t},\n\t\"overrides\": {\n\t\t\"leche\": {\n\t\t\t\"mocha\": \">=1.18\"\n\t\t}\n\t}\n}\n"
  },
  {
    "path": "src/box-command.js",
    "content": "'use strict';\n\nconst originalEmitWarning = process.emitWarning;\nprocess.emitWarning = (warning, ...args) => {\n\tconst message =\n\t\ttypeof warning === 'string' ? warning : warning?.message || '';\n\n\tif (message.includes('DEPRECATION WARNING')) {\n\t\treturn;\n\t}\n\t// If not the BoxClient deprecation warning, call the original emitWarning function\n\toriginalEmitWarning.call(process, warning, ...args);\n};\n\nconst { Command, Flags } = require('@oclif/core');\nconst chalk = require('chalk');\nconst { promisify } = require('node:util');\nconst _ = require('lodash');\nconst fs = require('node:fs');\nconst { mkdirp } = require('mkdirp');\nconst os = require('node:os');\nconst path = require('node:path');\nconst yaml = require('js-yaml');\nconst csv = require('csv');\nconst csvParse = promisify(csv.parse);\nconst csvStringify = promisify(csv.stringify);\nconst dateTime = require('date-fns');\nconst BoxSDK = require('box-node-sdk').default;\nconst BoxTSSDK = require('box-node-sdk/sdk-gen');\nconst BoxTsErrors = require('box-node-sdk/sdk-gen/box/errors');\nconst BoxCLIError = require('./cli-error');\nconst CLITokenCache = require('./token-cache');\nconst PaginationUtilities = require('./pagination-utils');\nconst utils = require('./util');\nconst pkg = require('../package.json');\nconst inquirer = require('./inquirer');\nconst { stringifyStream } = require('@discoveryjs/json-ext');\nconst progress = require('cli-progress');\nconst secureStorage = require('./secure-storage');\n\nconst DEBUG = require('./debug');\nconst stream = require('node:stream');\nconst pipeline = promisify(stream.pipeline);\n\nconst { Transform } = require('node:stream');\n\nconst KEY_MAPPINGS = {\n\turl: 'URL',\n\tid: 'ID',\n\tetag: 'ETag',\n\tsha1: 'SHA1',\n\ttemplateKey: 'Template Key',\n\tdisplayName: 'Display Name',\n\ttos: 'ToS',\n\tstatusCode: 'Status Code',\n\tboxReportsFolderPath: 'Box Reports Folder Path',\n\tboxReportsFolderName: 'Box Reports Folder Name (Deprecated)',\n\tboxReportsFileFormat: 'Box Reports File Format',\n\tboxDownloadsFolderPath: 'Box Downloads Folder Path',\n\tboxDownloadsFolderName: 'Box Downloads Folder Name (Deprecated)',\n\toutputJson: 'Output JSON',\n\tclientId: 'Client ID',\n\tenterpriseId: 'Enterprise ID',\n\tboxConfigFilePath: 'Box Config File Path',\n\thasInLinePrivateKey: 'Has Inline Private Key',\n\tprivateKeyPath: 'Private Key Path',\n\tdefaultAsUserId: 'Default As-User ID',\n\tuseDefaultAsUser: 'Use Default As-User',\n\tcacheTokens: 'Cache Tokens',\n\tip: 'IP',\n\toperationParams: 'Operation Params',\n\tcopyInstanceOnItemCopy: 'Copy Instance On Item Copy',\n};\n\nconst REQUIRED_FIELDS = ['type', 'id'];\n\nconst SDK_CONFIG = Object.freeze({\n\titerators: true,\n\tanalyticsClient: {\n\t\tversion: pkg.version,\n\t},\n\trequest: {\n\t\theaders: {\n\t\t\t'User-Agent': `Box CLI v${pkg.version}`,\n\t\t},\n\t},\n});\n\nconst CONFIG_FOLDER_PATH = path.join(os.homedir(), '.box');\nconst SETTINGS_FILE_PATH = path.join(CONFIG_FOLDER_PATH, 'settings.json');\nconst ENVIRONMENTS_FILE_PATH = path.join(\n\tCONFIG_FOLDER_PATH,\n\t'box_environments.json'\n);\nconst ENVIRONMENTS_KEYCHAIN_SERVICE = 'boxcli';\nconst ENVIRONMENTS_KEYCHAIN_ACCOUNT = 'Box';\n\nconst DEFAULT_ANALYTICS_CLIENT_NAME = 'box-cli';\n\n/**\n * Convert error objects to a stable debug-safe shape.\n *\n * @param {unknown} error A caught error object\n * @returns {Object} A reduced object for DEBUG logging\n */\nfunction getDebugErrorDetails(error) {\n\tif (!error || typeof error !== 'object') {\n\t\treturn { message: String(error) };\n\t}\n\treturn {\n\t\tname: error.name || 'Error',\n\t\tcode: error.code,\n\t\tmessage: error.message || String(error),\n\t\tstack: error.stack,\n\t};\n}\n\n/**\n * Parse a string value from CSV into the correct boolean value\n * @param {string|boolean} value The value to parse\n * @returns {boolean} The parsed value\n * @private\n */\nfunction getBooleanFlagValue(value) {\n\tlet trueValues = ['yes', 'y', 'true', '1', 't', 'on'];\n\tlet falseValues = ['no', 'n', 'false', '0', 'f', 'off'];\n\tif (typeof value === 'boolean') {\n\t\treturn value;\n\t} else if (trueValues.includes(value.toLowerCase())) {\n\t\treturn true;\n\t} else if (falseValues.includes(value.toLowerCase())) {\n\t\treturn false;\n\t}\n\tlet possibleValues = [...trueValues, ...falseValues].join(', ');\n\tthrow new Error(\n\t\t`Incorrect boolean value \"${value}\" passed. Possible values are ${possibleValues}`\n\t);\n}\n\n/**\n * Removes all the undefined values from the object\n *\n * @param {Object} obj The object to format for display\n * @returns {Object} The formatted object output\n */\nfunction removeUndefinedValues(obj) {\n\tif (typeof obj !== 'object' || obj === null) {\n\t\treturn obj;\n\t}\n\n\tif (Array.isArray(obj)) {\n\t\treturn obj.map((item) => removeUndefinedValues(item));\n\t}\n\n\tfor (const key of Object.keys(obj)) {\n\t\tif (obj[key] === undefined) {\n\t\t\tdelete obj[key];\n\t\t} else {\n\t\t\tobj[key] = removeUndefinedValues(obj[key]);\n\t\t}\n\t}\n\n\treturn obj;\n}\n\n/**\n * Add or subtract a given offset from a date\n *\n * @param {Date} date The date to offset\n * @param {int} timeLength The number of time units to offset by\n * @param {string} timeUnit The unit of time to offset by, in single-character shorthand\n * @returns {Date} The date with offset applied\n */\nfunction offsetDate(date, timeLength, timeUnit) {\n\tswitch (timeUnit) {\n\t\tcase 's': {\n\t\t\treturn dateTime.addSeconds(date, timeLength);\n\t\t}\n\t\tcase 'm': {\n\t\t\treturn dateTime.addMinutes(date, timeLength);\n\t\t}\n\t\tcase 'h': {\n\t\t\treturn dateTime.addHours(date, timeLength);\n\t\t}\n\t\tcase 'd': {\n\t\t\treturn dateTime.addDays(date, timeLength);\n\t\t}\n\t\tcase 'w': {\n\t\t\treturn dateTime.addWeeks(date, timeLength);\n\t\t}\n\t\tcase 'M': {\n\t\t\treturn dateTime.addMonths(date, timeLength);\n\t\t}\n\t\tcase 'y': {\n\t\t\treturn dateTime.addYears(date, timeLength);\n\t\t}\n\t\tdefault: {\n\t\t\tthrow new Error(`Invalid time unit: ${timeUnit}`);\n\t\t}\n\t}\n}\n\n/**\n * Formats an API key (e.g. field name) for human-readable display\n *\n * @param {string} key The key to format\n * @returns {string} The formatted key\n * @private\n */\nfunction formatKey(key) {\n\t// Converting camel case to snake case and then to title case\n\treturn key\n\t\t.replaceAll(/[A-Z]/gu, (letter) => `_${letter.toLowerCase()}`)\n\t\t.split('_')\n\t\t.map((s) => KEY_MAPPINGS[s] || _.capitalize(s))\n\t\t.join(' ');\n}\n\n/**\n * Formats an object's keys for human-readable output\n * @param {*} obj The thing to format\n * @returns {*} The formatted thing\n * @private\n */\nfunction formatObjectKeys(obj) {\n\t// No need to process primitive values\n\tif (typeof obj !== 'object' || obj === null) {\n\t\treturn obj;\n\t}\n\n\t// If type is Date, convert to ISO string\n\tif (obj instanceof Date) {\n\t\treturn obj.toISOString();\n\t}\n\n\t// Don't format metadata objects to avoid mangling keys\n\tif (obj.$type) {\n\t\treturn obj;\n\t}\n\n\tif (Array.isArray(obj)) {\n\t\treturn obj.map((el) => formatObjectKeys(el));\n\t}\n\n\tlet formattedObj = Object.create(null);\n\tfor (const key of Object.keys(obj)) {\n\t\tlet formattedKey = formatKey(key);\n\t\tformattedObj[formattedKey] = formatObjectKeys(obj[key]);\n\t}\n\n\treturn formattedObj;\n}\n\n/**\n * Formats an object for output by prettifying its keys\n * and rendering it in a more human-readable form (i.e. YAML)\n *\n * @param {Object} obj The object to format for display\n * @returns {string} The formatted object output\n * @private\n */\nfunction formatObject(obj) {\n\tlet outputData = formatObjectKeys(obj);\n\n\t// Other objects are formatted as YAML for human-readable output\n\tlet yamlString = yaml.dump(outputData, {\n\t\tindent: 4,\n\t\tnoRefs: true,\n\t});\n\n\t// The YAML library puts a trailing newline at the end of the string, which is\n\t// redundant with the automatic newline added by oclif when writing to stdout\n\treturn yamlString\n\t\t.replace(/\\r?\\n$/u, '')\n\t\t.replaceAll(/^([^:]+:)/gmu, (match, key) => chalk.cyan(key));\n}\n\n/**\n * Formats the object header, used to separate multiple objects in a collection\n *\n * @param {Object} obj The object to generate a header for\n * @returns {string} The header string\n * @private\n */\nfunction formatObjectHeader(obj) {\n\tif (!obj.type || !obj.id) {\n\t\treturn chalk`{dim ----------}`;\n\t}\n\treturn chalk`{dim ----- ${formatKey(obj.type)} ${obj.id} -----}`;\n}\n\n/**\n * Base class for all Box CLI commands\n */\nclass BoxCommand extends Command {\n\t// @TODO(2018-08-15): Move all fs methods used here to be async\n\n\t/**\n\t * Initialize before the command is run\n\t * @returns {void}\n\t */\n\tasync init() {\n\t\tDEBUG.init('Initializing Box CLI');\n\t\tlet originalArgs, originalFlags;\n\t\tif (\n\t\t\tthis.argv.some((arg) => arg.startsWith('--bulk-file-path')) &&\n\t\t\tObject.keys(this.constructor.flags).includes('bulk-file-path')\n\t\t) {\n\t\t\t// Set up the command for bulk run\n\t\t\tDEBUG.init('Preparing for bulk input');\n\t\t\tthis.isBulk = true;\n\t\t\t// eslint-disable-next-line unicorn/prefer-structured-clone\n\t\t\toriginalArgs = _.cloneDeep(this.constructor.args);\n\t\t\t// eslint-disable-next-line unicorn/prefer-structured-clone\n\t\t\toriginalFlags = _.cloneDeep(this.constructor.flags);\n\t\t\tthis.disableRequiredArgsAndFlags();\n\t\t}\n\n\t\tthis.supportsSecureStorage = secureStorage.available;\n\n\t\tlet { flags, args } = await this.parse(this.constructor);\n\n\t\tthis.flags = flags;\n\t\tthis.args = args;\n\t\tthis.settings = await this._loadSettings();\n\t\tthis.client = await this.getClient();\n\t\tthis.tsClient = await this.getTsClient();\n\n\t\tif (this.isBulk) {\n\t\t\tthis.constructor.args = originalArgs;\n\t\t\tthis.constructor.flags = originalFlags;\n\t\t\tthis.bulkOutputList = [];\n\t\t\tthis.bulkErrors = [];\n\t\t\tthis._singleRun = this.run;\n\t\t\tthis.run = this.bulkOutputRun;\n\t\t}\n\n\t\tDEBUG.execute(\n\t\t\t'Starting execution command: %s argv: %O',\n\t\t\tthis.id,\n\t\t\tthis.argv\n\t\t);\n\t}\n\n\t/**\n\t * Read in the input file and run the command once for each set of inputs\n\t * @returns {void}\n\t */\n\tasync bulkOutputRun() {\n\t\tconst allPossibleArgs = Object.keys(this.constructor.args || {});\n\t\tconst allPossibleFlags = Object.keys(this.constructor.flags || {});\n\t\t// Map from matchKey (arg/flag name in all lower-case characters) => {type, fieldKey}\n\t\tlet fieldMapping = Object.assign(\n\t\t\t{},\n\t\t\t...allPossibleArgs.map((arg) => ({\n\t\t\t\t[arg.toLowerCase()]: { type: 'arg', fieldKey: arg },\n\t\t\t})),\n\t\t\t...allPossibleFlags.map((flag) => ({\n\t\t\t\t[flag.replaceAll('-', '')]: { type: 'flag', fieldKey: flag },\n\t\t\t}))\n\t\t);\n\t\tlet bulkCalls = await this._parseBulkFile(\n\t\t\tthis.flags['bulk-file-path'],\n\t\t\tfieldMapping\n\t\t);\n\t\tlet bulkEntryIndex = 0;\n\t\tlet progressBar = new progress.Bar({\n\t\t\tformat: '[{bar}] {percentage}% | {value}/{total}',\n\t\t\tstopOnComplete: true,\n\t\t});\n\t\tprogressBar.start(bulkCalls.length, 0);\n\n\t\tfor (let bulkData of bulkCalls) {\n\t\t\tthis.argv = [];\n\t\t\tbulkEntryIndex += 1;\n\t\t\tthis._getArgsForBulkInput(allPossibleArgs, bulkData);\n\t\t\tthis._setFlagsForBulkInput(bulkData);\n\t\t\tawait this._handleAsUserSettings(bulkData);\n\t\t\tDEBUG.execute('Executing in bulk mode argv: %O', this.argv);\n\t\t\t// @TODO(2018-08-29): Convert this to a promise queue to improve performance\n\n\t\t\ttry {\n\t\t\t\tawait this._singleRun();\n\t\t\t} catch (error) {\n\t\t\t\t// In bulk mode, we don't want to write directly to console and kill the command\n\t\t\t\t// Instead, we should buffer the error output so subsequent commands might be able to succeed\n\t\t\t\tDEBUG.execute(\n\t\t\t\t\t'Caught error from bulk input entry %d',\n\t\t\t\t\tbulkEntryIndex\n\t\t\t\t);\n\t\t\t\tthis.bulkErrors.push({\n\t\t\t\t\tindex: bulkEntryIndex,\n\t\t\t\t\tdata: bulkData,\n\t\t\t\t\terror: this.wrapError(error),\n\t\t\t\t});\n\t\t\t}\n\n\t\t\tprogressBar.update(bulkEntryIndex);\n\t\t}\n\t\tthis.isBulk = false;\n\t\tDEBUG.execute('Leaving bulk mode and writing final output');\n\t\tawait this.output(this.bulkOutputList);\n\t\tthis._handleBulkErrors();\n\t}\n\n\t/**\n\t * Logs bulk processing errors if any occured.\n\t * @returns {void}\n\t * @private\n\t */\n\t_handleBulkErrors() {\n\t\tconst numErrors = this.bulkErrors.length;\n\t\tif (numErrors === 0) {\n\t\t\tthis.info(\n\t\t\t\tchalk`{green All bulk input entries processed successfully.}`\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\t\tthis.info(\n\t\t\tchalk`{redBright ${numErrors} entr${numErrors > 1 ? 'ies' : 'y'} failed!}`\n\t\t);\n\t\tfor (const errorInfo of this.bulkErrors) {\n\t\t\tthis.info(chalk`{dim ----------}`);\n\t\t\tlet entryData = errorInfo.data\n\t\t\t\t.map((o) => `    ${o.fieldKey}=${o.value}`)\n\t\t\t\t.join(os.EOL);\n\t\t\tthis.info(\n\t\t\t\tchalk`{redBright Entry ${errorInfo.index} (${\n\t\t\t\t\tos.EOL + entryData + os.EOL\n\t\t\t\t}) failed with error:}`\n\t\t\t);\n\t\t\tlet err = errorInfo.error;\n\t\t\tlet contextInfo;\n\t\t\tif (\n\t\t\t\terr.response &&\n\t\t\t\terr.response.body &&\n\t\t\t\terr.response.body.context_info\n\t\t\t) {\n\t\t\t\tcontextInfo = formatObject(err.response.body.context_info);\n\t\t\t\t// Remove color codes from context info\n\t\t\t\t// eslint-disable-next-line no-control-regex\n\t\t\t\tcontextInfo = contextInfo.replaceAll(/\\u001B\\[\\d+m/gu, '');\n\t\t\t\t// Remove \\n with os.EOL\n\t\t\t\tcontextInfo = contextInfo.replaceAll('\\n', os.EOL);\n\t\t\t}\n\t\t\tlet errMsg = chalk`{redBright ${\n\t\t\t\tthis.flags && this.flags.verbose ? err.stack : err.message\n\t\t\t}${os.EOL}${contextInfo ? contextInfo + os.EOL : ''}}`;\n\t\t\tthis.info(errMsg);\n\t\t}\n\t}\n\n\t/**\n\t * Set as-user header from the bulk file or use the default one.\n\t * @param {Array} bulkData Bulk data\n\t * @returns {Promise<void>} Returns nothing\n\t * @private\n\t */\n\tasync _handleAsUserSettings(bulkData) {\n\t\tlet asUser = bulkData.find((o) => o.fieldKey === 'as-user') || {};\n\t\tif (!_.isEmpty(asUser)) {\n\t\t\tif (_.isNil(asUser.value)) {\n\t\t\t\tlet environmentsObj = await this.getEnvironments();\n\t\t\t\tif (environmentsObj.default) {\n\t\t\t\t\tlet environment =\n\t\t\t\t\t\tenvironmentsObj.environments[environmentsObj.default];\n\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t'Using environment %s %O',\n\t\t\t\t\t\tenvironmentsObj.default,\n\t\t\t\t\t\tenvironment\n\t\t\t\t\t);\n\t\t\t\t\tif (environment.useDefaultAsUser) {\n\t\t\t\t\t\tthis.client.asUser(environment.defaultAsUserId);\n\t\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t\t'Impersonating default user ID %s',\n\t\t\t\t\t\t\tenvironment.defaultAsUserId\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.client.asSelf();\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tthis.client.asSelf();\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis.client.asUser(asUser.value);\n\t\t\t\tDEBUG.init('Impersonating user ID %s', asUser.value);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Include flag values from command line first,\n\t * they'll automatically be overwritten/combined with later values by the oclif parser.\n\t * @param {Array} bulkData Bulk data\n\t * @returns {void}\n\t * @private\n\t */\n\t_setFlagsForBulkInput(bulkData) {\n\t\tconst bulkDataFlags = new Set(\n\t\t\tbulkData\n\t\t\t\t.filter((o) => o.type === 'flag' && !_.isNil(o.value))\n\t\t\t\t.map((o) => o.fieldKey)\n\t\t);\n\t\tfor (const flag of Object.keys(this.flags)\n\t\t\t.filter((flag) => flag !== 'bulk-file-path') // Remove the bulk file path flag so we don't recurse!\n\t\t\t.filter((flag) => !bulkDataFlags.has(flag))) {\n\t\t\t// Some flags can be specified multiple times in a single command. For these flags, their value is an array of user inputted values.\n\t\t\t// For these flags, we iterate through their values and add each one as a separate flag to comply with oclif\n\t\t\tif (Array.isArray(this.flags[flag])) {\n\t\t\t\tfor (const value of this.flags[flag]) {\n\t\t\t\t\tthis._addFlagToArgv(flag, value);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthis._addFlagToArgv(flag, this.flags[flag]);\n\t\t\t}\n\t\t}\n\t\t// Include all flag values from bulk input, which will override earlier ones\n\t\t// from the command line\n\t\tfor (const o of bulkData\n\t\t\t// Remove the bulk file path flag so we don't recurse!\n\t\t\t.filter(\n\t\t\t\t(o) => o.type === 'flag' && o.fieldKey !== 'bulk-file-path'\n\t\t\t))\n\t\t\tthis._addFlagToArgv(o.fieldKey, o.value);\n\t}\n\n\t/**\n\t * For each possible arg, find the correct value between bulk input and values given on the command line.\n\t * @param {Array} allPossibleArgs All possible args\n\t * @param {Array} bulkData Bulk data\n\t * @returns {void}\n\t * @private\n\t */\n\t_getArgsForBulkInput(allPossibleArgs, bulkData) {\n\t\tfor (let arg of allPossibleArgs) {\n\t\t\tlet bulkArg = bulkData.find((o) => o.fieldKey === arg) || {};\n\t\t\tif (!_.isNil(bulkArg.value)) {\n\t\t\t\t// Use value from bulk input file when available\n\t\t\t\tthis.argv.push(bulkArg.value);\n\t\t\t} else if (this.args[arg]) {\n\t\t\t\t// Fall back to value from command line\n\t\t\t\tthis.argv.push(this.args[arg]);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Parses file wilk bulk commands\n\t * @param {String} filePath Path to file with bulk commands\n\t * @param {Array} fieldMapping Data to parse\n\t * @returns {Promise<*>} Returns parsed data\n\t * @private\n\t */\n\tasync _parseBulkFile(filePath, fieldMapping) {\n\t\tconst fileExtension = path.extname(filePath);\n\t\tconst fileContents = this._readBulkFile(filePath);\n\t\tlet bulkCalls;\n\t\tif (fileExtension === '.json') {\n\t\t\tbulkCalls = this._handleJsonFile(fileContents, fieldMapping);\n\t\t} else if (fileExtension === '.csv') {\n\t\t\tbulkCalls = await this._handleCsvFile(fileContents, fieldMapping);\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t`Input file had extension \"${fileExtension}\", but only .json and .csv are supported`\n\t\t\t);\n\t\t}\n\t\t// Filter out any undefined values, which can arise when the input file contains extraneous keys\n\t\tbulkCalls = bulkCalls.map((args) =>\n\t\t\targs.filter((o) => o !== undefined)\n\t\t);\n\t\tDEBUG.execute(\n\t\t\t'Read %d entries from bulk file %s',\n\t\t\tbulkCalls.length,\n\t\t\tthis.flags['bulk-file-path']\n\t\t);\n\t\treturn bulkCalls;\n\t}\n\n\t/**\n\t * Parses CSV file\n\t * @param {Object} fileContents File content to parse\n\t * @param {Array} fieldMapping Field mapings\n\t * @returns {Promise<string|null|*>} Returns parsed data\n\t * @private\n\t */\n\tasync _handleCsvFile(fileContents, fieldMapping) {\n\t\tlet parsedData = await csvParse(fileContents, {\n\t\t\tbom: true,\n\t\t\tdelimiter: ',',\n\t\t\tcast(value, context) {\n\t\t\t\tif (value.length === 0) {\n\t\t\t\t\t// Regard unquoted empty values as null\n\t\t\t\t\treturn context.quoting ? '' : null;\n\t\t\t\t}\n\t\t\t\treturn value;\n\t\t\t},\n\t\t});\n\t\tif (parsedData.length < 2) {\n\t\t\tthrow new Error(\n\t\t\t\t'CSV input file should contain the headers row and at least on data row'\n\t\t\t);\n\t\t}\n\t\t// @NOTE: We don't parse the CSV into an aray of Objects\n\t\t// and instead mainatain a separate array of headers, in\n\t\t// order to ensure that ordering is maintained in the keys\n\t\tlet headers = parsedData.shift().map((key) => {\n\t\t\tlet keyParts = key.match(/(.*)_\\d+$/u);\n\t\t\tlet someKey = keyParts ? keyParts[1] : key;\n\t\t\treturn someKey.toLowerCase().replaceAll(/[-_]/gu, '');\n\t\t});\n\t\treturn parsedData.map((values) =>\n\t\t\tvalues.map((value, index) => {\n\t\t\t\tlet key = headers[index];\n\t\t\t\tlet field = fieldMapping[key];\n\t\t\t\treturn field ? { ...field, value } : undefined;\n\t\t\t})\n\t\t);\n\t}\n\n\t/**\n\t * Parses JSON file\n\t * @param {Object} fileContents File content to parse\n\t * @param {Array} fieldMapping Field mapings\n\t * @returns {*} Returns parsed data\n\t * @private\n\t */\n\t_handleJsonFile(fileContents, fieldMapping) {\n\t\tlet parsedData;\n\t\ttry {\n\t\t\tlet jsonFile = JSON.parse(fileContents);\n\t\t\tparsedData = Object.hasOwn(jsonFile, 'entries')\n\t\t\t\t? jsonFile.entries\n\t\t\t\t: jsonFile;\n\t\t} catch (error) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t`Could not parse JSON input file ${this.flags['bulk-file-path']}`,\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\t\tif (!Array.isArray(parsedData)) {\n\t\t\tthrow new TypeError(\n\t\t\t\t'Expected input file to contain an array of input objects, but none found'\n\t\t\t);\n\t\t}\n\t\t// Translate each row object to an array of {type, fieldKey, value}, to be handled below\n\t\treturn parsedData.map(function flattenObjectToArgs(obj) {\n\t\t\t// One top-level object key can map to multiple args/flags, so we need to deeply flatten after mapping\n\t\t\treturn _.flatMapDeep(obj, (value, key) => {\n\t\t\t\tlet matchKey = key.toLowerCase().replaceAll(/[-_]/gu, '');\n\t\t\t\tlet field = fieldMapping[matchKey];\n\t\t\t\tif (_.isPlainObject(value)) {\n\t\t\t\t\t// Map e.g. { item: { id: 12345, type: folder } } => { item: 12345, itemtype: folder }\n\t\t\t\t\t// @NOTE: For now, we only support nesting keys this way one level deep\n\t\t\t\t\treturn Object.keys(value).map((nestedKey) => {\n\t\t\t\t\t\tlet nestedMatchKey =\n\t\t\t\t\t\t\tmatchKey +\n\t\t\t\t\t\t\tnestedKey.toLowerCase().replaceAll(/[-_]/gu, '');\n\t\t\t\t\t\tlet nestedField = fieldMapping[nestedMatchKey];\n\t\t\t\t\t\treturn nestedField\n\t\t\t\t\t\t\t? { ...nestedField, value: value[nestedKey] }\n\t\t\t\t\t\t\t: undefined;\n\t\t\t\t\t});\n\t\t\t\t} else if (Array.isArray(value)) {\n\t\t\t\t\t// Arrays can be one of two things: an array of values for a single key,\n\t\t\t\t\t// or an array of grouped flags/args as objects\n\t\t\t\t\t// First, check if everything in the array is either all object or all non-object\n\t\t\t\t\tlet types = value.map((t) => typeof t);\n\t\t\t\t\tif (\n\t\t\t\t\t\ttypes.some((t) => t !== 'object') &&\n\t\t\t\t\t\ttypes.includes('object')\n\t\t\t\t\t) {\n\t\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t\t'Mixed types in bulk input JSON array; use strings or Objects'\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\t// If everything in the array is objects, handle each one as a group of flags and args\n\t\t\t\t\t// by recursively parsing that object into args\n\t\t\t\t\tif (types[0] === 'object') {\n\t\t\t\t\t\treturn value.map((o) => flattenObjectToArgs(o));\n\t\t\t\t\t}\n\t\t\t\t\t// If the array is of values for this field, just return those\n\t\t\t\t\treturn field\n\t\t\t\t\t\t? value.map((v) => ({ ...field, value: v }))\n\t\t\t\t\t\t: [];\n\t\t\t\t}\n\t\t\t\treturn field ? { ...field, value } : undefined;\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Returns bulk file contents\n\t * @param {String} filePath Path to bulk file\n\t * @returns {Buffer} Bulk file contents\n\t * @private\n\t */\n\t_readBulkFile(filePath) {\n\t\ttry {\n\t\t\tconst fileContents = fs.readFileSync(filePath);\n\t\t\tDEBUG.execute('Read bulk input file at %s', filePath);\n\t\t\treturn fileContents;\n\t\t} catch (error) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t`Could not open input file ${filePath}`,\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Writes a given flag value to the command's argv array\n\t *\n\t * @param {string} flag The flag name\n\t * @param {*} flagValue The flag value\n\t * @returns {void}\n\t * @private\n\t */\n\t_addFlagToArgv(flag, flagValue) {\n\t\tif (_.isNil(flagValue)) {\n\t\t\treturn;\n\t\t}\n\n\t\tif (this.constructor.flags[flag].type === 'boolean') {\n\t\t\tif (getBooleanFlagValue(flagValue)) {\n\t\t\t\tthis.argv.push(`--${flag}`);\n\t\t\t} else {\n\t\t\t\tthis.argv.push(`--no-${flag}`);\n\t\t\t}\n\t\t} else {\n\t\t\tthis.argv.push(`--${flag}=${flagValue}`);\n\t\t}\n\t}\n\n\t/**\n\t * Ensure that all args and flags for the command are not marked as required,\n\t * to avoid issues when filling in required values from the input file.\n\t * @returns {void}\n\t */\n\tdisableRequiredArgsAndFlags() {\n\t\tif (this.constructor.args !== undefined) {\n\t\t\tfor (const key of Object.keys(this.constructor.args)) {\n\t\t\t\tthis.constructor.args[key].required = false;\n\t\t\t}\n\t\t}\n\n\t\tif (this.constructor.flags !== undefined) {\n\t\t\tfor (const key of Object.keys(this.constructor.flags)) {\n\t\t\t\tthis.constructor.flags[key].required = false;\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Instantiate the SDK client for making API calls\n\t *\n\t * @returns {BoxClient} The client for making API calls in the command\n\t */\n\tasync getClient() {\n\t\t// Allow some commands (e.g. configure:environments:add, login) to skip client setup so they can run\n\t\tif (this.constructor.noClient) {\n\t\t\treturn null;\n\t\t}\n\t\tlet environmentsObj = await this.getEnvironments();\n\t\tconst environment =\n\t\t\tenvironmentsObj.environments[environmentsObj.default] || {};\n\t\tconst { authMethod } = environment;\n\n\t\tlet client;\n\t\tif (this.flags.token) {\n\t\t\tDEBUG.init('Using passed in token %s', this.flags.token);\n\t\t\tlet sdk = new BoxSDK({\n\t\t\t\tclientID: '',\n\t\t\t\tclientSecret: '',\n\t\t\t\t...SDK_CONFIG,\n\t\t\t});\n\t\t\tthis._configureSdk(sdk, { ...SDK_CONFIG });\n\t\t\tthis.sdk = sdk;\n\t\t\tclient = sdk.getBasicClient(this.flags.token);\n\t\t} else if (authMethod === 'ccg') {\n\t\t\tDEBUG.init('Using Client Credentials Grant Authentication');\n\n\t\t\tconst { clientId, clientSecret, ccgUser } = environment;\n\n\t\t\tif (!clientId || !clientSecret) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t'You need to have a default environment with clientId and clientSecret in order to use CCG'\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlet configObj;\n\t\t\ttry {\n\t\t\t\tconfigObj = JSON.parse(\n\t\t\t\t\tfs.readFileSync(environment.boxConfigFilePath)\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t'Could not read environments config file',\n\t\t\t\t\terror\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst { enterpriseID } = configObj;\n\t\t\tconst sdk = new BoxSDK({\n\t\t\t\tclientID: clientId,\n\t\t\t\tclientSecret,\n\t\t\t\tenterpriseID,\n\t\t\t\t...SDK_CONFIG,\n\t\t\t});\n\t\t\tthis._configureSdk(sdk, { ...SDK_CONFIG });\n\t\t\tthis.sdk = sdk;\n\t\t\tclient = ccgUser\n\t\t\t\t? sdk.getCCGClientForUser(ccgUser)\n\t\t\t\t: sdk.getAnonymousClient();\n\t\t} else if (\n\t\t\tenvironmentsObj.default &&\n\t\t\tenvironmentsObj.environments[environmentsObj.default].authMethod ===\n\t\t\t\t'oauth20'\n\t\t) {\n\t\t\ttry {\n\t\t\t\tDEBUG.init(\n\t\t\t\t\t'Using environment %s %O',\n\t\t\t\t\tenvironmentsObj.default,\n\t\t\t\t\tenvironment\n\t\t\t\t);\n\t\t\t\tlet tokenCache = new CLITokenCache(environmentsObj.default);\n\n\t\t\t\tlet sdk = new BoxSDK({\n\t\t\t\t\tclientID: environment.clientId,\n\t\t\t\t\tclientSecret: environment.clientSecret,\n\t\t\t\t\t...SDK_CONFIG,\n\t\t\t\t});\n\t\t\t\tthis._configureSdk(sdk, { ...SDK_CONFIG });\n\t\t\t\tthis.sdk = sdk;\n\t\t\t\tlet tokenInfo = await new Promise((resolve, reject) => {\n\t\t\t\t\ttokenCache.read((error, localTokenInfo) => {\n\t\t\t\t\t\tif (error) {\n\t\t\t\t\t\t\treject(error);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresolve(localTokenInfo);\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\tclient = sdk.getPersistentClient(tokenInfo, tokenCache);\n\t\t\t} catch {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t`Can't load the default OAuth environment \"${environmentsObj.default}\". Please reauthorize selected environment, login again or provide a token.`\n\t\t\t\t);\n\t\t\t}\n\t\t} else if (environmentsObj.default) {\n\t\t\tDEBUG.init(\n\t\t\t\t'Using environment %s %O',\n\t\t\t\tenvironmentsObj.default,\n\t\t\t\tenvironment\n\t\t\t);\n\t\t\tlet tokenCache =\n\t\t\t\tenvironment.cacheTokens === false\n\t\t\t\t\t? null\n\t\t\t\t\t: new CLITokenCache(environmentsObj.default);\n\t\t\tlet configObj;\n\t\t\ttry {\n\t\t\t\tconfigObj = JSON.parse(\n\t\t\t\t\tfs.readFileSync(environment.boxConfigFilePath)\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t'Could not read environments config file',\n\t\t\t\t\terror\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (!environment.hasInLinePrivateKey) {\n\t\t\t\ttry {\n\t\t\t\t\tconfigObj.boxAppSettings.appAuth.privateKey =\n\t\t\t\t\t\tfs.readFileSync(environment.privateKeyPath, 'utf8');\n\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t'Loaded JWT private key from %s',\n\t\t\t\t\t\tenvironment.privateKeyPath\n\t\t\t\t\t);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t`Could not read private key file ${environment.privateKeyPath}`,\n\t\t\t\t\t\terror\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tthis.sdk = BoxSDK.getPreconfiguredInstance(configObj);\n\t\t\tthis._configureSdk(this.sdk, { ...SDK_CONFIG });\n\n\t\t\tclient = this.sdk.getAppAuthClient(\n\t\t\t\t'enterprise',\n\t\t\t\tenvironment.enterpriseId,\n\t\t\t\ttokenCache\n\t\t\t);\n\t\t\tDEBUG.init('Initialized client from environment config');\n\t\t} else {\n\t\t\t// No environments set up yet!\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t`No default environment found.\n\t\t\t\tIt looks like you haven't configured the Box CLI yet.\n\t\t\t\tSee this command for help adding an environment: box configure:environments:add --help\n\t\t\t\tOr, supply a token with your command with --token.`.replaceAll(/^\\s+/gmu, '')\n\t\t\t);\n\t\t}\n\n\t\t// Using the as-user flag should have precedence over the environment setting\n\t\tif (this.flags['as-user']) {\n\t\t\tclient.asUser(this.flags['as-user']);\n\t\t\tDEBUG.init(\n\t\t\t\t'Impersonating user ID %s using the ID provided via the --as-user flag',\n\t\t\t\tthis.flags['as-user']\n\t\t\t);\n\t\t} else if (!this.flags.token && environment.useDefaultAsUser) {\n\t\t\t// We don't want to use any environment settings if a token is passed in the command\n\t\t\tclient.asUser(environment.defaultAsUserId);\n\t\t\tDEBUG.init(\n\t\t\t\t'Impersonating default user ID %s using environment configuration',\n\t\t\t\tenvironment.defaultAsUserId\n\t\t\t);\n\t\t}\n\t\treturn client;\n\t}\n\n\t/**\n\t * Instantiate the TypeScript SDK client for making API calls\n\t *\n\t * @returns {BoxTSSDK.BoxClient} The TypeScript SDK client for making API calls in the command\n\t */\n\tasync getTsClient() {\n\t\t// Allow some commands (e.g. configure:environments:add, login) to skip client setup so they can run\n\t\tif (this.constructor.noClient) {\n\t\t\treturn null;\n\t\t}\n\t\tlet environmentsObj = await this.getEnvironments();\n\t\tconst environment =\n\t\t\tenvironmentsObj.environments[environmentsObj.default] || {};\n\t\tconst { authMethod } = environment;\n\n\t\tlet client;\n\t\tif (this.flags.token) {\n\t\t\tDEBUG.init('Using passed in token %s', this.flags.token);\n\t\t\tlet tsSdkAuth = new BoxTSSDK.BoxDeveloperTokenAuth({\n\t\t\t\ttoken: this.flags.token,\n\t\t\t});\n\t\t\tclient = new BoxTSSDK.BoxClient({\n\t\t\t\tauth: tsSdkAuth,\n\t\t\t});\n\t\t\tclient = this._configureTsSdk(client, SDK_CONFIG);\n\t\t} else if (authMethod === 'ccg') {\n\t\t\tDEBUG.init('Using Client Credentials Grant Authentication');\n\n\t\t\tconst { clientId, clientSecret, ccgUser } = environment;\n\n\t\t\tif (!clientId || !clientSecret) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t'You need to have a default environment with clientId and clientSecret in order to use CCG'\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tlet configObj;\n\t\t\ttry {\n\t\t\t\tconfigObj = JSON.parse(\n\t\t\t\t\tfs.readFileSync(environment.boxConfigFilePath)\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t'Could not read environments config file',\n\t\t\t\t\terror\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst { enterpriseID } = configObj;\n\t\t\tconst tokenCache =\n\t\t\t\tenvironment.cacheTokens === false\n\t\t\t\t\t? null\n\t\t\t\t\t: new CLITokenCache(environmentsObj.default);\n\t\t\tlet ccgConfig = new BoxTSSDK.CcgConfig(\n\t\t\t\tccgUser\n\t\t\t\t\t? {\n\t\t\t\t\t\t\tclientId,\n\t\t\t\t\t\t\tclientSecret,\n\t\t\t\t\t\t\tuserId: ccgUser,\n\t\t\t\t\t\t\ttokenStorage: tokenCache,\n\t\t\t\t\t\t}\n\t\t\t\t\t: {\n\t\t\t\t\t\t\tclientId,\n\t\t\t\t\t\t\tclientSecret,\n\t\t\t\t\t\t\tenterpriseId: enterpriseID,\n\t\t\t\t\t\t\ttokenStorage: tokenCache,\n\t\t\t\t\t\t}\n\t\t\t);\n\t\t\tlet ccgAuth = new BoxTSSDK.BoxCcgAuth({ config: ccgConfig });\n\t\t\tclient = new BoxTSSDK.BoxClient({\n\t\t\t\tauth: ccgAuth,\n\t\t\t});\n\t\t\tclient = this._configureTsSdk(client, SDK_CONFIG);\n\t\t} else if (\n\t\t\tenvironmentsObj.default &&\n\t\t\tenvironmentsObj.environments[environmentsObj.default].authMethod ===\n\t\t\t\t'oauth20'\n\t\t) {\n\t\t\ttry {\n\t\t\t\tDEBUG.init(\n\t\t\t\t\t'Using environment %s %O',\n\t\t\t\t\tenvironmentsObj.default,\n\t\t\t\t\tenvironment\n\t\t\t\t);\n\t\t\t\tconst tokenCache = new CLITokenCache(environmentsObj.default);\n\t\t\t\tconst oauthConfig = new BoxTSSDK.OAuthConfig({\n\t\t\t\t\tclientId: environment.clientId,\n\t\t\t\t\tclientSecret: environment.clientSecret,\n\t\t\t\t\ttokenStorage: tokenCache,\n\t\t\t\t});\n\t\t\t\tconst oauthAuth = new BoxTSSDK.BoxOAuth({\n\t\t\t\t\tconfig: oauthConfig,\n\t\t\t\t});\n\t\t\t\tclient = new BoxTSSDK.BoxClient({ auth: oauthAuth });\n\t\t\t\tclient = this._configureTsSdk(client, SDK_CONFIG);\n\t\t\t} catch {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t`Can't load the default OAuth environment \"${environmentsObj.default}\". Please reauthorize selected environment, login again or provide a token.`\n\t\t\t\t);\n\t\t\t}\n\t\t} else if (environmentsObj.default) {\n\t\t\tDEBUG.init(\n\t\t\t\t'Using environment %s %O',\n\t\t\t\tenvironmentsObj.default,\n\t\t\t\tenvironment\n\t\t\t);\n\t\t\tlet tokenCache =\n\t\t\t\tenvironment.cacheTokens === false\n\t\t\t\t\t? null\n\t\t\t\t\t: new CLITokenCache(environmentsObj.default);\n\t\t\tlet configObj;\n\t\t\ttry {\n\t\t\t\tconfigObj = JSON.parse(\n\t\t\t\t\tfs.readFileSync(environment.boxConfigFilePath)\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t'Could not read environments config file',\n\t\t\t\t\terror\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (!environment.hasInLinePrivateKey) {\n\t\t\t\ttry {\n\t\t\t\t\tconfigObj.boxAppSettings.appAuth.privateKey =\n\t\t\t\t\t\tfs.readFileSync(environment.privateKeyPath, 'utf8');\n\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t'Loaded JWT private key from %s',\n\t\t\t\t\t\tenvironment.privateKeyPath\n\t\t\t\t\t);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t`Could not read private key file ${environment.privateKeyPath}`,\n\t\t\t\t\t\terror\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst jwtConfig = new BoxTSSDK.JwtConfig({\n\t\t\t\tclientId: configObj.boxAppSettings.clientID,\n\t\t\t\tclientSecret: configObj.boxAppSettings.clientSecret,\n\t\t\t\tjwtKeyId: configObj.boxAppSettings.appAuth.publicKeyID,\n\t\t\t\tprivateKey: configObj.boxAppSettings.appAuth.privateKey,\n\t\t\t\tprivateKeyPassphrase:\n\t\t\t\t\tconfigObj.boxAppSettings.appAuth.passphrase,\n\t\t\t\tenterpriseId: environment.enterpriseId,\n\t\t\t\ttokenStorage: tokenCache,\n\t\t\t});\n\t\t\tlet jwtAuth = new BoxTSSDK.BoxJwtAuth({ config: jwtConfig });\n\t\t\tclient = new BoxTSSDK.BoxClient({ auth: jwtAuth });\n\n\t\t\tDEBUG.init('Initialized client from environment config');\n\t\t\tif (environment.useDefaultAsUser) {\n\t\t\t\tclient = client.withAsUserHeader(environment.defaultAsUserId);\n\t\t\t\tDEBUG.init(\n\t\t\t\t\t'Impersonating default user ID %s',\n\t\t\t\t\tenvironment.defaultAsUserId\n\t\t\t\t);\n\t\t\t}\n\t\t\tclient = this._configureTsSdk(client, SDK_CONFIG);\n\t\t} else {\n\t\t\t// No environments set up yet!\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t`No default environment found.\n\t\t\t\tIt looks like you haven't configured the Box CLI yet.\n\t\t\t\tSee this command for help adding an environment: box configure:environments:add --help\n\t\t\t\tOr, supply a token with your command with --token.`.replaceAll(/^\\s+/gmu, '')\n\t\t\t);\n\t\t}\n\t\tif (this.flags['as-user']) {\n\t\t\tclient = client.withAsUserHeader(this.flags['as-user']);\n\t\t\tDEBUG.init('Impersonating user ID %s', this.flags['as-user']);\n\t\t}\n\t\treturn client;\n\t}\n\n\t/**\n\t * Configures SDK by using values from settings.json file\n\t * @param {*} sdk to configure\n\t * @param {*} config Additional options to use while building configuration\n\t * @returns {void}\n\t */\n\t_configureSdk(sdk, config = {}) {\n\t\tconst clientSettings = { ...config };\n\t\tif (this.settings.enableProxy) {\n\t\t\tclientSettings.proxy = this.settings.proxy;\n\t\t}\n\t\tif (this.settings.apiRootURL) {\n\t\t\tclientSettings.apiRootURL = this.settings.apiRootURL;\n\t\t}\n\t\tif (this.settings.uploadAPIRootURL) {\n\t\t\tclientSettings.uploadAPIRootURL = this.settings.uploadAPIRootURL;\n\t\t}\n\t\tif (this.settings.authorizeRootURL) {\n\t\t\tclientSettings.authorizeRootURL = this.settings.authorizeRootURL;\n\t\t}\n\t\tif (this.settings.numMaxRetries) {\n\t\t\tclientSettings.numMaxRetries = this.settings.numMaxRetries;\n\t\t}\n\t\tif (this.settings.retryIntervalMS) {\n\t\t\tclientSettings.retryIntervalMS = this.settings.retryIntervalMS;\n\t\t}\n\t\tif (this.settings.uploadRequestTimeoutMS) {\n\t\t\tclientSettings.uploadRequestTimeoutMS =\n\t\t\t\tthis.settings.uploadRequestTimeoutMS;\n\t\t}\n\t\tclientSettings.analyticsClient.name =\n\t\t\tthis.settings.enableAnalyticsClient &&\n\t\t\tthis.settings.analyticsClient.name\n\t\t\t\t? `${DEFAULT_ANALYTICS_CLIENT_NAME} ${this.settings.analyticsClient.name}`\n\t\t\t\t: DEFAULT_ANALYTICS_CLIENT_NAME;\n\n\t\tif (Object.keys(clientSettings).length > 0) {\n\t\t\tDEBUG.init('SDK client settings %s', clientSettings);\n\t\t\tsdk.configure(clientSettings);\n\t\t}\n\t}\n\n\t/**\n\t * Configures TS SDK by using values from settings.json file\n\t *\n\t * @param {BoxTSSDK.BoxClient} client to configure\n\t * @param {Object} config Additional options to use while building configuration\n\t * @returns {BoxTSSDK.BoxClient} The configured client\n\t */\n\t_configureTsSdk(client, config) {\n\t\tlet additionalHeaders = config.request.headers;\n\t\tlet customBaseURL = {\n\t\t\tbaseUrl: 'https://api.box.com',\n\t\t\tuploadUrl: 'https://upload.box.com/api',\n\t\t\toauth2Url: 'https://account.box.com/api/oauth2',\n\t\t};\n\t\tif (this.settings.enableProxy) {\n\t\t\tclient = client.withProxy(this.settings.proxy);\n\t\t}\n\t\tif (this.settings.apiRootURL) {\n\t\t\tcustomBaseURL.baseUrl = this.settings.apiRootURL;\n\t\t}\n\t\tif (this.settings.uploadAPIRootURL) {\n\t\t\tcustomBaseURL.uploadUrl = this.settings.uploadAPIRootURL;\n\t\t}\n\t\tif (this.settings.authorizeRootURL) {\n\t\t\tcustomBaseURL.oauth2Url = this.settings.authorizeRootURL;\n\t\t}\n\t\tclient = client.withCustomBaseUrls(customBaseURL);\n\n\t\tif (this.settings.numMaxRetries) {\n\t\t\t// Not supported in TS SDK\n\t\t}\n\t\tif (this.settings.retryIntervalMS) {\n\t\t\t// Not supported in TS SDK\n\t\t}\n\t\tif (this.settings.uploadRequestTimeoutMS) {\n\t\t\t// Not supported in TS SDK\n\t\t}\n\t\tadditionalHeaders['X-Box-UA'] =\n\t\t\tthis.settings.enableAnalyticsClient &&\n\t\t\tthis.settings.analyticsClient.name\n\t\t\t\t? `${DEFAULT_ANALYTICS_CLIENT_NAME} ${this.settings.analyticsClient.name}`\n\t\t\t\t: DEFAULT_ANALYTICS_CLIENT_NAME;\n\t\tclient = client.withExtraHeaders(additionalHeaders);\n\t\tDEBUG.init('TS SDK configured with settings from settings.json');\n\n\t\treturn client;\n\t}\n\n\t/**\n\t * Returns true when raw API JSON output was requested.\n\t *\n\t * @returns {boolean} True if raw JSON output should be used\n\t * @private\n\t */\n\t_wantsRawJsonOutput() {\n\t\treturn Boolean(this.flags && this.flags['raw-json']);\n\t}\n\n\t/**\n\t * Preserves default output behavior while adding raw JSON support.\n\t *\n\t * The generated TypeScript client can expose response objects with normalized\n\t * field names that do not match the original API schema. That behavior was\n\t * introduced as newer commands moved to `tsClient`. To fix the JSON output\n\t * shape without a breaking change, commands that support `--raw-json` use this\n\t * wrapper on the top-level response object before calling `output()`.\n\t *\n\t * @param {*} content The content to potentially replace with rawData\n\t * @returns {*} The content to send to output formatting\n\t */\n\tgetOutputContentWithRawJsonSupport(content) {\n\t\tif (typeof content === 'object' && content !== null) {\n\t\t\tif (this._wantsRawJsonOutput()) {\n\t\t\t\treturn content.rawData ?? content;\n\t\t\t}\n\n\t\t\tif (Object.hasOwn(content, 'rawData')) {\n\t\t\t\tconst output = { ...content };\n\t\t\t\tdelete output.rawData;\n\t\t\t\treturn output;\n\t\t\t}\n\t\t}\n\n\t\treturn content;\n\t}\n\n\t/**\n\t * Format data for output to stdout\n\t * @param {*} content The content to output\n\t * @returns {Promise<void>} A promise resolving when output is handled\n\t */\n\tasync output(content) {\n\t\tif (this.isBulk) {\n\t\t\tthis.bulkOutputList.push(content);\n\t\t\tDEBUG.output(\n\t\t\t\t'Added command output to bulk list total: %d',\n\t\t\t\tthis.bulkOutputList.length\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tlet formattedOutputData;\n\t\tif (Array.isArray(content)) {\n\t\t\t// Format each object individually and then flatten in case this an array of arrays,\n\t\t\t// which happens when a command that outputs a collection gets run in bulk\n\t\t\tconst formattedOutputResults = await Promise.all(\n\t\t\t\tcontent.map((o) => this._formatOutputObject(o))\n\t\t\t);\n\t\t\tformattedOutputData = formattedOutputResults.flat();\n\t\t\tDEBUG.output(\n\t\t\t\t'Formatted %d output entries for display',\n\t\t\t\tcontent.length\n\t\t\t);\n\t\t} else {\n\t\t\tformattedOutputData = await this._formatOutputObject(content);\n\t\t\tDEBUG.output('Formatted output content for display');\n\t\t}\n\t\tlet outputFormat = this._getOutputFormat();\n\t\tDEBUG.output('Using %s output format', outputFormat);\n\t\tDEBUG.output(formattedOutputData);\n\n\t\tlet writeFunc;\n\t\tlet logFunc;\n\t\tlet stringifiedOutput;\n\n\t\t// remove all the undefined values from the object\n\t\tformattedOutputData = removeUndefinedValues(formattedOutputData);\n\n\t\tif (outputFormat === 'json') {\n\t\t\tstringifiedOutput = stringifyStream(formattedOutputData, null, 4);\n\n\t\t\tlet appendNewLineTransform = new Transform({\n\t\t\t\ttransform(chunk, encoding, callback) {\n\t\t\t\t\tcallback(null, chunk);\n\t\t\t\t},\n\t\t\t\tflush(callback) {\n\t\t\t\t\tthis.push(os.EOL);\n\t\t\t\t\tcallback();\n\t\t\t\t},\n\t\t\t});\n\n\t\t\twriteFunc = async (savePath) => {\n\t\t\t\tawait pipeline(\n\t\t\t\t\tstringifiedOutput,\n\t\t\t\t\tappendNewLineTransform,\n\t\t\t\t\tfs.createWriteStream(savePath, { encoding: 'utf8' })\n\t\t\t\t);\n\t\t\t};\n\n\t\t\tlogFunc = async () => {\n\t\t\t\tawait this.logStream(stringifiedOutput);\n\t\t\t};\n\t\t} else {\n\t\t\tstringifiedOutput =\n\t\t\t\tawait this._stringifyOutput(formattedOutputData);\n\n\t\t\twriteFunc = async (savePath) => {\n\t\t\t\tawait utils.writeFileAsync(\n\t\t\t\t\tsavePath,\n\t\t\t\t\tstringifiedOutput + os.EOL,\n\t\t\t\t\t{\n\t\t\t\t\t\tencoding: 'utf8',\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t};\n\n\t\t\tlogFunc = () => this.log(stringifiedOutput);\n\t\t}\n\t\treturn this._writeOutput(writeFunc, logFunc);\n\t}\n\n\t/**\n\t * Check if max-items has been reached.\n\t *\n\t * @param {number} maxItems Total number of items to return\n\t * @param {number} itemsCount Current number of items\n\t * @returns {boolean} True if limit has been reached, otherwise false\n\t * @private\n\t */\n\tmaxItemsReached(maxItems, itemsCount) {\n\t\treturn maxItems && itemsCount >= maxItems;\n\t}\n\n\t/**\n\t * Fetch all marker-based pages from a TypeScript SDK endpoint.\n\t *\n\t * @param {Function} fetchPage Callback that receives query params and returns a paged response\n\t * @param {Object} queryParams Base query params for each request\n\t * @param {number} [maxItemsOverride] Optional max items override for advanced use\n\t * @returns {Promise<Object[]>} Aggregated marker-based response entries\n\t */\n\tasync markerPagination(fetchPage, queryParams, maxItemsOverride) {\n\t\tconst normalizedQueryParams = queryParams || {};\n\t\tconst paginationFlags = {\n\t\t\t'max-items':\n\t\t\t\tmaxItemsOverride === undefined\n\t\t\t\t\t? this.flags['max-items']\n\t\t\t\t\t: maxItemsOverride,\n\t\t};\n\t\tconst paginationOptions =\n\t\t\tPaginationUtilities.handlePagination(paginationFlags);\n\t\tconst maxItems =\n\t\t\tpaginationFlags['max-items'] === undefined\n\t\t\t\t? paginationOptions.limit\n\t\t\t\t: paginationFlags['max-items'];\n\n\t\tlet remaining = maxItems;\n\t\tconst entries = [];\n\t\tconst pageLimit = paginationOptions.limit;\n\t\tlet marker;\n\n\t\twhile (remaining > 0) {\n\t\t\tconst pageQueryParams = {\n\t\t\t\t...normalizedQueryParams,\n\t\t\t\tlimit: Math.min(pageLimit, remaining),\n\t\t\t};\n\n\t\t\tif (marker) {\n\t\t\t\tpageQueryParams.marker = marker;\n\t\t\t}\n\n\t\t\tconst page = await fetchPage(pageQueryParams);\n\t\t\tconst rawPage =\n\t\t\t\ttypeof page?.rawData === 'object' && page.rawData !== null\n\t\t\t\t\t? page.rawData\n\t\t\t\t\t: page;\n\t\t\tconst pageEntries = rawPage.entries || page.entries || [];\n\t\t\tentries.push(...pageEntries);\n\t\t\tremaining -= pageEntries.length;\n\t\t\tmarker = page.nextMarker || page.next_marker;\n\n\t\t\tif (!marker || pageEntries.length === 0) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn entries;\n\t}\n\n\t/**\n\t * Prepare the output data by:\n\t *   1) Unrolling an iterator into an array\n\t *   2) Filtering out unwanted object fields\n\t *\n\t * @param {*} obj The raw object containing output data\n\t * @returns {*} The formatted output data\n\t * @private\n\t */\n\tasync _formatOutputObject(obj) {\n\t\tlet output = obj;\n\n\t\t// Pass primitive content types through\n\t\tif (typeof output !== 'object' || output === null) {\n\t\t\treturn output;\n\t\t}\n\n\t\t// Unroll iterator into array\n\t\tif (typeof obj.next === 'function') {\n\t\t\toutput = [];\n\t\t\tlet entry = await obj.next();\n\t\t\twhile (!entry.done) {\n\t\t\t\toutput.push(entry.value);\n\n\t\t\t\tif (\n\t\t\t\t\tthis.maxItemsReached(this.flags['max-items'], output.length)\n\t\t\t\t) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tentry = await obj.next();\n\t\t\t}\n\t\t\tDEBUG.output('Unrolled iterable into %d entries', output.length);\n\t\t}\n\n\t\tif (this.flags['id-only']) {\n\t\t\toutput = Array.isArray(output)\n\t\t\t\t? this.filterOutput(output, 'id')\n\t\t\t\t: output.id;\n\t\t} else {\n\t\t\toutput = this.filterOutput(output, this.flags.fields);\n\t\t}\n\n\t\treturn output;\n\t}\n\n\t/**\n\t * Get the output format (and file extension) based on the settings and flags set\n\t *\n\t * @returns {string} The file extension/format to use for output\n\t * @private\n\t */\n\t_getOutputFormat() {\n\t\tif (this.flags.json) {\n\t\t\treturn 'json';\n\t\t}\n\n\t\t// Raw API payloads are only intended for JSON output, so `--raw-json`\n\t\t// implicitly promotes the format to JSON without changing default behavior.\n\t\tif (this._wantsRawJsonOutput()) {\n\t\t\treturn 'json';\n\t\t}\n\n\t\tif (this.flags.csv) {\n\t\t\treturn 'csv';\n\t\t}\n\n\t\tif (this.flags.save || this.flags['save-to-file-path']) {\n\t\t\treturn this.settings.boxReportsFileFormat || 'txt';\n\t\t}\n\n\t\tif (this.settings.outputJson) {\n\t\t\treturn 'json';\n\t\t}\n\n\t\treturn 'txt';\n\t}\n\n\t/**\n\t * Converts output data to a string based on the type of content and flags the user\n\t * has specified regarding output format\n\t *\n\t * @param {*} outputData The data to output\n\t * @returns {string} Promise resolving to the output data as a string\n\t * @private\n\t */\n\tasync _stringifyOutput(outputData) {\n\t\tlet outputFormat = this._getOutputFormat();\n\n\t\tif (typeof outputData !== 'object') {\n\t\t\tDEBUG.output('Primitive output cast to string');\n\t\t\treturn String(outputData);\n\t\t} else if (outputFormat === 'csv') {\n\t\t\tlet csvString = await csvStringify(\n\t\t\t\tthis.formatForTableAndCSVOutput(outputData)\n\t\t\t);\n\t\t\t// The CSV library puts a trailing newline at the end of the string, which is\n\t\t\t// redundant with the automatic newline added by oclif when writing to stdout\n\t\t\tDEBUG.output('Processed output as CSV');\n\t\t\treturn csvString.replace(/\\r?\\n$/u, '');\n\t\t} else if (Array.isArray(outputData)) {\n\t\t\tlet str = outputData\n\t\t\t\t.map(\n\t\t\t\t\t(o) => `${formatObjectHeader(o)}${os.EOL}${formatObject(o)}`\n\t\t\t\t)\n\t\t\t\t.join(os.EOL.repeat(2));\n\t\t\tDEBUG.output('Processed collection into human-readable output');\n\t\t\treturn str;\n\t\t}\n\n\t\tlet str = formatObject(outputData);\n\t\tDEBUG.output('Processed human-readable output');\n\t\treturn str;\n\t}\n\n\t/**\n\t * Generate an appropriate default filename for writing\n\t * the output of this command to disk.\n\t *\n\t * @returns {string} The output file name\n\t * @private\n\t */\n\t_getOutputFileName() {\n\t\tlet extension = this._getOutputFormat();\n\t\treturn `${this.id.replaceAll(':', '-')}-${dateTime.format(\n\t\t\tnew Date(),\n\t\t\t'YYYY-MM-DD_HH_mm_ss_SSS'\n\t\t)}.${extension}`;\n\t}\n\n\t/**\n\t * Write output to its final destination, either a file or stdout\n\t * @param {Function} writeFunc Function used to save output to a file\n\t * @param {Function} logFunc Function used to print output to stdout\n\t * @returns {Promise<void>} A promise resolving when output is written\n\t * @private\n\t */\n\tasync _writeOutput(writeFunc, logFunc) {\n\t\tif (this.flags.save) {\n\t\t\tDEBUG.output('Writing output to default location on disk');\n\t\t\tlet filePath = path.join(\n\t\t\t\tthis.settings.boxReportsFolderPath,\n\t\t\t\tthis._getOutputFileName()\n\t\t\t);\n\t\t\ttry {\n\t\t\t\tawait writeFunc(filePath);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t`Could not write output to file at ${filePath}`,\n\t\t\t\t\terror\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.info(chalk`{green Output written to ${filePath}}`);\n\t\t} else if (this.flags['save-to-file-path']) {\n\t\t\tlet savePath = this.flags['save-to-file-path'];\n\t\t\tif (fs.existsSync(savePath)) {\n\t\t\t\tif (fs.statSync(savePath).isDirectory()) {\n\t\t\t\t\t// Append default file name and write into the provided directory\n\t\t\t\t\tsavePath = path.join(savePath, this._getOutputFileName());\n\t\t\t\t\tDEBUG.output(\n\t\t\t\t\t\t'Output path is a directory, will write to %s',\n\t\t\t\t\t\tsavePath\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tDEBUG.output('File already exists at %s', savePath);\n\t\t\t\t\t// Ask if the user want to overwrite the file\n\t\t\t\t\tlet shouldOverwrite = await this.confirm(\n\t\t\t\t\t\t`File ${savePath} already exists — overwrite?`\n\t\t\t\t\t);\n\n\t\t\t\t\tif (!shouldOverwrite) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\ttry {\n\t\t\t\tDEBUG.output(\n\t\t\t\t\t'Writing output to specified location on disk: %s',\n\t\t\t\t\tsavePath\n\t\t\t\t);\n\t\t\t\tawait writeFunc(savePath);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t`Could not write output to file at ${savePath}`,\n\t\t\t\t\terror\n\t\t\t\t);\n\t\t\t}\n\t\t\tthis.info(chalk`{green Output written to ${savePath}}`);\n\t\t} else {\n\t\t\tDEBUG.output('Writing output to terminal');\n\t\t\tawait logFunc();\n\t\t}\n\n\t\tDEBUG.output('Finished writing output');\n\t}\n\n\t/**\n\t * Ask a user to confirm something, respecting the default --yes flag\n\t *\n\t * @param {string} promptText The text of the prompt to the user\n\t * @param {boolean} defaultValue The default value of the prompt\n\t * @returns {Promise<boolean>} A promise resolving to a boolean that is true iff the user confirmed\n\t */\n\tasync confirm(promptText, defaultValue = false) {\n\t\tif (this.flags.yes) {\n\t\t\treturn true;\n\t\t}\n\n\t\tlet answers = await inquirer.prompt([\n\t\t\t{\n\t\t\t\tname: 'confirmation',\n\t\t\t\tmessage: promptText,\n\t\t\t\ttype: 'confirm',\n\t\t\t\tdefault: defaultValue,\n\t\t\t},\n\t\t]);\n\n\t\treturn answers.confirmation;\n\t}\n\n\t/**\n\t * Writes output to stderr — this should be used for informational output.  For example, a message\n\t * stating that an item has been deleted.\n\t *\n\t * @param {string} content The message to output\n\t * @returns {void}\n\t */\n\tinfo(content) {\n\t\tif (!this.flags.quiet) {\n\t\t\tprocess.stderr.write(`${content}${os.EOL}`);\n\t\t}\n\t}\n\n\t/**\n\t * Writes output to stderr — this should be used for informational output.  For example, a message\n\t * stating that an item has been deleted.\n\t *\n\t * @param {string} content The message to output\n\t * @returns {void}\n\t */\n\tlog(content) {\n\t\tif (!this.flags.quiet) {\n\t\t\tprocess.stdout.write(`${content}${os.EOL}`);\n\t\t}\n\t}\n\n\t/**\n\t * Writes stream output to stderr — this should be used for informational output.  For example, a message\n\t * stating that an item has been deleted.\n\t *\n\t * @param {ReadableStream} content The message to output\n\t * @returns {void}\n\t */\n\tasync logStream(content) {\n\t\tif (!this.flags.quiet) {\n\t\t\t// For Node 12 when process.stdout is in pipeline it's not emitting end event correctly and it freezes.\n\t\t\t// See - https://github.com/nodejs/node/issues/34059\n\t\t\t// Using promise for now.\n\t\t\tcontent.pipe(process.stdout);\n\n\t\t\tawait new Promise((resolve, reject) => {\n\t\t\t\tcontent\n\t\t\t\t\t.on('end', () => {\n\t\t\t\t\t\tprocess.stdout.write(os.EOL);\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t})\n\t\t\t\t\t.on('error', (err) => {\n\t\t\t\t\t\treject(err);\n\t\t\t\t\t});\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Wraps filtered error in an error with a user-friendly description\n\t *\n\t * @param {Error} err  The thrown error\n\t * @returns {Error} Error wrapped in an error with user friendly description\n\t */\n\twrapError(err) {\n\t\tlet messageMap = {\n\t\t\t'invalid_grant - Refresh token has expired':\n\t\t\t\t'Your refresh token has expired. \\nPlease run this command \"box login --name <ENVIRONMENT_NAME> --reauthorize\" to reauthorize selected environment and then run your command again.',\n\t\t\t'Expired Auth: Auth code or refresh token has expired':\n\t\t\t\t'Authentication failed: token is invalid or expired. OAuth: run \"box login --reauthorize\". JWT/CCG: tokens are refreshed automatically, so this usually means app credentials or environment configuration must be fixed. You can also provide a fresh token with --token.',\n\t\t};\n\n\t\tfor (const key in messageMap) {\n\t\t\tif (err.message.includes(key)) {\n\t\t\t\treturn new BoxCLIError(messageMap[key], err);\n\t\t\t}\n\t\t}\n\n\t\treturn err;\n\t}\n\n\t/**\n\t * Handles an error thrown within a command\n\t *\n\t * @param {Error} err  The thrown error\n\t * @returns {void}\n\t */\n\tasync catch(err) {\n\t\tconst AUTH_FAILED_HINT =\n\t\t\t'Authentication failed: token is invalid or expired. OAuth: run \"box login --reauthorize\". JWT/CCG: tokens are refreshed automatically, so a 401 usually means app credentials or environment configuration must be fixed. You can also provide a fresh token with --token.';\n\t\tif (\n\t\t\terr instanceof BoxTsErrors.BoxApiError &&\n\t\t\terr.responseInfo &&\n\t\t\terr.responseInfo.body\n\t\t) {\n\t\t\tconst responseInfo = err.responseInfo;\n\t\t\tlet errorMessage = `Unexpected API Response [${responseInfo.body.status} ${responseInfo.body.message} | ${responseInfo.body.request_id}] ${responseInfo.body.code} - ${responseInfo.body.message}`;\n\t\t\tif (responseInfo.body.status === 401) {\n\t\t\t\terrorMessage += `\\n${AUTH_FAILED_HINT}`;\n\t\t\t}\n\t\t\terr = new BoxCLIError(errorMessage, err);\n\t\t}\n\t\tif (err instanceof BoxTsErrors.BoxSdkError) {\n\t\t\ttry {\n\t\t\t\tlet errorObj = JSON.parse(err.message);\n\t\t\t\tif (errorObj.message) {\n\t\t\t\t\terr = new BoxCLIError(errorObj.message, err);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tDEBUG.execute('Error parsing BoxSdkError message: %s', error);\n\t\t\t}\n\t\t}\n\t\ttry {\n\t\t\t// Let the oclif default handler run first, since it handles the help and version flags there\n\t\t\t/* eslint-disable promise/no-promise-in-callback */\n\t\t\tDEBUG.execute('Running framework error handler');\n\t\t\tawait super.catch(this.wrapError(err));\n\t\t} catch (error) {\n\t\t\t// The oclif default catch handler rethrows most errors; handle those here\n\t\t\tDEBUG.execute('Handling re-thrown error in base command handler');\n\n\t\t\tif (error.code === 'EEXIT') {\n\t\t\t\t// oclif throws this when it handled the error itself and wants to exit, so just let it do that\n\t\t\t\tDEBUG.execute('Got EEXIT code, exiting immediately');\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tlet contextInfo;\n\t\t\tif (\n\t\t\t\terror.response &&\n\t\t\t\terror.response.body &&\n\t\t\t\terror.response.body.context_info\n\t\t\t) {\n\t\t\t\tcontextInfo = formatObject(error.response.body.context_info);\n\t\t\t\t// Remove color codes from context info\n\t\t\t\t// eslint-disable-next-line no-control-regex\n\t\t\t\tcontextInfo = contextInfo.replaceAll(/\\u001B\\[\\d+m/gu, '');\n\t\t\t\t// Remove \\n with os.EOL\n\t\t\t\tcontextInfo = contextInfo.replaceAll('\\n', os.EOL);\n\t\t\t}\n\t\t\tlet statusHint = '';\n\t\t\tconst statusCode = error.statusCode || error.response?.statusCode;\n\t\t\tif (statusCode === 401) {\n\t\t\t\tstatusHint = AUTH_FAILED_HINT;\n\t\t\t}\n\t\t\tlet errorMsg = chalk`{redBright ${\n\t\t\t\tthis.flags && this.flags.verbose ? error.stack : error.message\n\t\t\t}${os.EOL}${contextInfo ? contextInfo + os.EOL : ''}${statusHint ? statusHint + os.EOL : ''}}`;\n\n\t\t\t// Write the error message but let the process exit gracefully with error code so stderr gets written out\n\t\t\t// @NOTE: Exiting the process in the callback enables tests to mock out stderr and run to completion!\n\n\t\t\tprocess.stderr.write(errorMsg, () => {\n\t\t\t\tprocess.exitCode = 2;\n\t\t\t});\n\t\t}\n\t}\n\n\t/**\n\t * Final hook that executes for all commands, regardless of if an error occurred\n\t * @param {Error} [err] An error, if one occurred\n\t * @returns {void}\n\t */\n\tasync finally(/* err */) {\n\t\t// called after run and catch regardless of whether or not the command errored\n\t}\n\n\t/**\n\t * Filter out unwanted fields from the output object(s)\n\t *\n\t * @param {Object|Object[]} output The output object(s)\n\t * @param {string} [fields] Comma-separated list of fields to include\n\t * @returns {Object|Object[]} The filtered object(s) for output\n\t */\n\tfilterOutput(output, fields) {\n\t\tif (!fields) {\n\t\t\treturn output;\n\t\t}\n\t\tfields = [\n\t\t\t...REQUIRED_FIELDS,\n\t\t\t...fields.split(',').filter((f) => !REQUIRED_FIELDS.includes(f)),\n\t\t];\n\t\tDEBUG.output('Filtering output with fields: %O', fields);\n\t\tif (Array.isArray(output)) {\n\t\t\toutput = output.map((o) =>\n\t\t\t\ttypeof o === 'object' ? _.pick(o, fields) : o\n\t\t\t);\n\t\t} else if (typeof output === 'object') {\n\t\t\toutput = _.pick(output, fields);\n\t\t}\n\t\treturn output;\n\t}\n\n\t/**\n\t * Flatten nested objects for output to a table/CSV\n\t *\n\t * @param {Object[]} objectArray The objects that will be output\n\t * @returns {Array[]} The formatted output\n\t */\n\tformatForTableAndCSVOutput(objectArray) {\n\t\tlet formattedData = [];\n\t\tif (!Array.isArray(objectArray)) {\n\t\t\tobjectArray = [objectArray];\n\t\t\tDEBUG.output('Creating tabular output from single object');\n\t\t}\n\n\t\tlet keyPaths = [];\n\t\tfor (let object of objectArray) {\n\t\t\tkeyPaths = _.union(keyPaths, this.getNestedKeys(object));\n\t\t}\n\n\t\tDEBUG.output('Found %d keys for tabular output', keyPaths.length);\n\t\tformattedData.push(keyPaths);\n\t\tfor (let object of objectArray) {\n\t\t\tlet row = [];\n\t\t\tif (typeof object === 'object') {\n\t\t\t\tfor (let keyPath of keyPaths) {\n\t\t\t\t\tlet value = _.get(object, keyPath);\n\t\t\t\t\tif (value === null || value === undefined) {\n\t\t\t\t\t\trow.push('');\n\t\t\t\t\t} else {\n\t\t\t\t\t\trow.push(value);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\trow.push(object);\n\t\t\t}\n\t\t\tDEBUG.output('Processed row with %d values', row.length);\n\t\t\tformattedData.push(row);\n\t\t}\n\t\tDEBUG.output(\n\t\t\t'Processed %d rows of tabular output',\n\t\t\tformattedData.length - 1\n\t\t);\n\t\treturn formattedData;\n\t}\n\n\t/**\n\t * Extracts all keys from an object and flattens them\n\t *\n\t * @param {Object} object The object to extract flattened keys from\n\t * @returns {string[]} The array of flattened keys\n\t */\n\tgetNestedKeys(object) {\n\t\tlet keys = [];\n\t\tif (typeof object === 'object') {\n\t\t\tfor (let key in object) {\n\t\t\t\tif (\n\t\t\t\t\ttypeof object[key] === 'object' &&\n\t\t\t\t\t!Array.isArray(object[key])\n\t\t\t\t) {\n\t\t\t\t\tlet subKeys = this.getNestedKeys(object[key]);\n\t\t\t\t\tsubKeys = subKeys.map((x) => `${key}.${x}`);\n\t\t\t\t\tkeys = [...keys, ...subKeys];\n\t\t\t\t} else {\n\t\t\t\t\tkeys.push(key);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn keys;\n\t}\n\n\t/**\n\t * Converts time interval shorthand like 5w, -3d, etc to timestamps. It also ensures any timestamp\n\t * passed in is properly formatted for API calls.\n\t *\n\t * @param {string} time The command lint input string for the datetime\n\t * @returns {string} The full RFC3339-formatted datetime string in UTC\n\t */\n\tstatic normalizeDateString(time) {\n\t\t// Attempt to parse date as timestamp or string\n\t\tlet newDate = /^\\d+$/u.test(time)\n\t\t\t? dateTime.parse(Number.parseInt(time, 10) * 1000)\n\t\t\t: dateTime.parse(time);\n\t\tif (!dateTime.isValid(newDate)) {\n\t\t\tlet parsedOffset = time.match(/^(-?)((?:\\d+[smhdwMy])+)$/u);\n\t\t\tif (parsedOffset) {\n\t\t\t\tlet sign = parsedOffset[1] === '-' ? -1 : 1,\n\t\t\t\t\toffset = parsedOffset[2];\n\n\t\t\t\t// Transform a string like \"-1d2h3m\" into an array of arg arrays, e.g.:\n\t\t\t\t// [ [-1, \"d\"], [-2, \"h\"], [-3, \"m\"] ]\n\t\t\t\tlet argPairs = _.chunk(offset.split(/(\\d+)/u).slice(1), 2).map(\n\t\t\t\t\t(pair) => [sign * Number.parseInt(pair[0], 10), pair[1]]\n\t\t\t\t);\n\n\t\t\t\t// Successively apply the offsets to the current time\n\t\t\t\tnewDate = new Date();\n\t\t\t\tfor (const args of argPairs) {\n\t\t\t\t\tnewDate = offsetDate(newDate, ...args);\n\t\t\t\t}\n\t\t\t} else if (time === 'now') {\n\t\t\t\tnewDate = new Date();\n\t\t\t} else {\n\t\t\t\tthrow new BoxCLIError(`Cannot parse date format \"${time}\"`);\n\t\t\t}\n\t\t}\n\n\t\t// Format the timezone to RFC3339 format for the Box API\n\t\t// Also always use UTC timezone for consistency in tests\n\t\treturn newDate.toISOString().replace(/\\.\\d{3}Z$/u, '+00:00');\n\t}\n\n\t/**\n\t * Writes updated settings to disk\n\t *\n\t * @param {Object} updatedSettings The settings object to write\n\t * @returns {void}\n\t */\n\tupdateSettings(updatedSettings) {\n\t\tthis.settings = Object.assign(this.settings, updatedSettings);\n\t\ttry {\n\t\t\tfs.writeFileSync(\n\t\t\t\tSETTINGS_FILE_PATH,\n\t\t\t\tJSON.stringify(this.settings, null, 4),\n\t\t\t\t'utf8'\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t`Could not write settings file ${SETTINGS_FILE_PATH}`,\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\t\treturn this.settings;\n\t}\n\n\t/**\n\t * Read the current set of environments from disk\n\t *\n\t * @returns {Object} The parsed environment information\n\t */\n\tasync getEnvironments() {\n\t\tif (this.supportsSecureStorage) {\n\t\t\tDEBUG.init(\n\t\t\t\t'Attempting secure storage read via %s service=\"%s\" account=\"%s\"',\n\t\t\t\tsecureStorage.backend,\n\t\t\t\tENVIRONMENTS_KEYCHAIN_SERVICE,\n\t\t\t\tENVIRONMENTS_KEYCHAIN_ACCOUNT\n\t\t\t);\n\t\t\ttry {\n\t\t\t\tconst password = await secureStorage.getPassword(\n\t\t\t\t\tENVIRONMENTS_KEYCHAIN_SERVICE,\n\t\t\t\t\tENVIRONMENTS_KEYCHAIN_ACCOUNT\n\t\t\t\t);\n\t\t\t\tif (password) {\n\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t'Successfully loaded environments from secure storage (%s)',\n\t\t\t\t\t\tsecureStorage.backend\n\t\t\t\t\t);\n\t\t\t\t\treturn JSON.parse(password);\n\t\t\t\t}\n\t\t\t\tDEBUG.init(\n\t\t\t\t\t'Secure storage returned empty result for service=\"%s\" account=\"%s\"',\n\t\t\t\t\tENVIRONMENTS_KEYCHAIN_SERVICE,\n\t\t\t\t\tENVIRONMENTS_KEYCHAIN_ACCOUNT\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tDEBUG.init(\n\t\t\t\t\t'Failed to read from secure storage (%s), falling back to file: %O',\n\t\t\t\t\tsecureStorage.backend,\n\t\t\t\t\tgetDebugErrorDetails(error)\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tDEBUG.init(\n\t\t\t\t'Skipping secure storage read: platform=%s available=%s',\n\t\t\t\tprocess.platform,\n\t\t\t\tsecureStorage.available\n\t\t\t);\n\t\t}\n\n\t\t// Try to read from file (fallback or no secure storage)\n\t\ttry {\n\t\t\tif (fs.existsSync(ENVIRONMENTS_FILE_PATH)) {\n\t\t\t\tDEBUG.init(\n\t\t\t\t\t'Attempting environments fallback file read at %s',\n\t\t\t\t\tENVIRONMENTS_FILE_PATH\n\t\t\t\t);\n\t\t\t\treturn JSON.parse(fs.readFileSync(ENVIRONMENTS_FILE_PATH));\n\t\t\t}\n\t\t\tDEBUG.init(\n\t\t\t\t'Environments fallback file does not exist at %s',\n\t\t\t\tENVIRONMENTS_FILE_PATH\n\t\t\t);\n\t\t} catch (error) {\n\t\t\tDEBUG.init(\n\t\t\t\t'Failed to read environments from file: %O',\n\t\t\t\tgetDebugErrorDetails(error)\n\t\t\t);\n\t\t}\n\n\t\t// No environments found in either location\n\t\tthrow new BoxCLIError(\n\t\t\t`Could not read environments. No environments found in secure storage or file ${ENVIRONMENTS_FILE_PATH}`\n\t\t);\n\t}\n\n\t/**\n\t * Writes updated environment information to disk\n\t *\n\t * @param {Object} updatedEnvironments The environment information to write\n\t * @param {Object} environments use to override current environment\n\t * @returns {void}\n\t */\n\tasync updateEnvironments(updatedEnvironments, environments) {\n\t\tif (environments === undefined) {\n\t\t\tenvironments = await this.getEnvironments();\n\t\t}\n\t\tObject.assign(environments, updatedEnvironments);\n\n\t\tlet storedInSecureStorage = false;\n\n\t\tif (this.supportsSecureStorage) {\n\t\t\tDEBUG.init(\n\t\t\t\t'Attempting secure storage write via %s service=\"%s\" account=\"%s\"',\n\t\t\t\tsecureStorage.backend,\n\t\t\t\tENVIRONMENTS_KEYCHAIN_SERVICE,\n\t\t\t\tENVIRONMENTS_KEYCHAIN_ACCOUNT\n\t\t\t);\n\t\t\ttry {\n\t\t\t\tawait secureStorage.setPassword(\n\t\t\t\t\tENVIRONMENTS_KEYCHAIN_SERVICE,\n\t\t\t\t\tENVIRONMENTS_KEYCHAIN_ACCOUNT,\n\t\t\t\t\tJSON.stringify(environments)\n\t\t\t\t);\n\t\t\t\tstoredInSecureStorage = true;\n\t\t\t\tDEBUG.init(\n\t\t\t\t\t'Stored environment configuration in secure storage (%s)',\n\t\t\t\t\tsecureStorage.backend\n\t\t\t\t);\n\t\t\t\tif (fs.existsSync(ENVIRONMENTS_FILE_PATH)) {\n\t\t\t\t\tfs.unlinkSync(ENVIRONMENTS_FILE_PATH);\n\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t'Removed environment configuration file after migrating to secure storage'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tDEBUG.init(\n\t\t\t\t\t'Could not store credentials in secure storage (%s), falling back to file: %O',\n\t\t\t\t\tsecureStorage.backend,\n\t\t\t\t\tgetDebugErrorDetails(error)\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tDEBUG.init(\n\t\t\t\t'Skipping secure storage write: platform=%s available=%s',\n\t\t\t\tprocess.platform,\n\t\t\t\tsecureStorage.available\n\t\t\t);\n\t\t}\n\n\t\t// Write to file if secure storage failed or not available\n\t\tif (!storedInSecureStorage) {\n\t\t\ttry {\n\t\t\t\tlet fileContents = JSON.stringify(environments, null, 4);\n\t\t\t\tfs.writeFileSync(ENVIRONMENTS_FILE_PATH, fileContents, 'utf8');\n\n\t\t\t\tif (process.platform === 'linux' && this.supportsSecureStorage) {\n\t\t\t\t\tthis.info(\n\t\t\t\t\t\t'Could not store credentials in secure storage, falling back to file.' +\n\t\t\t\t\t\t\t' To enable secure storage on Linux, install libsecret-1-dev package.'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t`Could not write environments config file ${ENVIRONMENTS_FILE_PATH}`,\n\t\t\t\t\terror\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn environments;\n\t}\n\n\t/**\n\t * Initialize the CLI by creating the necessary configuration files on disk\n\t * in the users' home directory, then read and parse the CLI settings file.\n\t *\n\t * @returns {Object} The parsed settings\n\t * @private\n\t */\n\tasync _loadSettings() {\n\t\ttry {\n\t\t\tif (!fs.existsSync(CONFIG_FOLDER_PATH)) {\n\t\t\t\tmkdirp.sync(CONFIG_FOLDER_PATH);\n\t\t\t\tDEBUG.init('Created config folder at %s', CONFIG_FOLDER_PATH);\n\t\t\t}\n\n\t\t\t// Check if environments exist (in secure storage or file)\n\t\t\tlet environmentsExist = false;\n\t\t\ttry {\n\t\t\t\tconst environments = await this.getEnvironments();\n\t\t\t\t// Check if there are any environments configured\n\t\t\t\tif (\n\t\t\t\t\tenvironments &&\n\t\t\t\t\tenvironments.environments &&\n\t\t\t\t\tObject.keys(environments.environments).length > 0\n\t\t\t\t) {\n\t\t\t\t\tenvironmentsExist = true;\n\t\t\t\t\tDEBUG.init('Found existing environments in storage');\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\t// No environments found, need to create defaults\n\t\t\t\tDEBUG.init('No existing environments found: %s', error.message);\n\t\t\t}\n\n\t\t\tif (!environmentsExist) {\n\t\t\t\t// Create default environments (will be stored in secure storage if available)\n\t\t\t\tawait this.updateEnvironments(\n\t\t\t\t\t{},\n\t\t\t\t\tthis._getDefaultEnvironments()\n\t\t\t\t);\n\t\t\t\tDEBUG.init('Created default environments configuration');\n\t\t\t}\n\n\t\t\tif (!fs.existsSync(SETTINGS_FILE_PATH)) {\n\t\t\t\tlet settingsJSON = JSON.stringify(\n\t\t\t\t\tthis._getDefaultSettings(),\n\t\t\t\t\tnull,\n\t\t\t\t\t4\n\t\t\t\t);\n\t\t\t\tfs.writeFileSync(SETTINGS_FILE_PATH, settingsJSON, 'utf8');\n\t\t\t\tDEBUG.init(\n\t\t\t\t\t'Created settings file at %s %O',\n\t\t\t\t\tSETTINGS_FILE_PATH,\n\t\t\t\t\tsettingsJSON\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Could not initialize CLI home directory',\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\n\t\tlet settings;\n\t\ttry {\n\t\t\tsettings = JSON.parse(fs.readFileSync(SETTINGS_FILE_PATH));\n\t\t\tsettings = Object.assign(this._getDefaultSettings(), settings);\n\t\t\tDEBUG.init('Loaded settings %O', settings);\n\t\t} catch (error) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t`Could not read CLI settings file at ${SETTINGS_FILE_PATH}`,\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tif (!fs.existsSync(settings.boxReportsFolderPath)) {\n\t\t\t\tmkdirp.sync(settings.boxReportsFolderPath);\n\t\t\t\tDEBUG.init(\n\t\t\t\t\t'Created reports folder at %s',\n\t\t\t\t\tsettings.boxReportsFolderPath\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!fs.existsSync(settings.boxDownloadsFolderPath)) {\n\t\t\t\tmkdirp.sync(settings.boxDownloadsFolderPath);\n\t\t\t\tDEBUG.init(\n\t\t\t\t\t'Created downloads folder at %s',\n\t\t\t\t\tsettings.boxDownloadsFolderPath\n\t\t\t\t);\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Failed creating CLI working directory',\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\n\t\treturn settings;\n\t}\n\n\t/**\n\t * Get the default settings object\n\t *\n\t * @returns {Object} The default settings object\n\t * @private\n\t */\n\t_getDefaultSettings() {\n\t\treturn {\n\t\t\tboxReportsFolderPath: path.join(\n\t\t\t\tos.homedir(),\n\t\t\t\t'Documents/Box-Reports'\n\t\t\t),\n\t\t\tboxReportsFileFormat: 'txt',\n\t\t\tboxDownloadsFolderPath: path.join(\n\t\t\t\tos.homedir(),\n\t\t\t\t'Downloads/Box-Downloads'\n\t\t\t),\n\t\t\toutputJson: false,\n\t\t\tenableProxy: false,\n\t\t\tproxy: {\n\t\t\t\turl: null,\n\t\t\t\tusername: null,\n\t\t\t\tpassword: null,\n\t\t\t},\n\t\t\tenableAnalyticsClient: false,\n\t\t\tanalyticsClient: {\n\t\t\t\tname: null,\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * Get the default environments object\n\t *\n\t * @returns {Object} The default environments object\n\t * @private\n\t */\n\t_getDefaultEnvironments() {\n\t\treturn {\n\t\t\tdefault: null,\n\t\t\tenvironments: {},\n\t\t};\n\t}\n}\n\nBoxCommand.flags = {\n\ttoken: Flags.string({\n\t\tchar: 't',\n\t\tdescription: 'Provide a token to perform this call',\n\t}),\n\t'as-user': Flags.string({ description: 'Provide an ID for a user' }),\n\t// @NOTE: This flag is not read anywhere directly; the chalk library automatically turns off color when it's passed\n\t'no-color': Flags.boolean({\n\t\tdescription: 'Turn off colors for logging',\n\t}),\n\tjson: Flags.boolean({\n\t\tdescription: 'Output formatted JSON',\n\t\texclusive: ['csv'],\n\t}),\n\tcsv: Flags.boolean({\n\t\tdescription: 'Output formatted CSV',\n\t\texclusive: ['json'],\n\t}),\n\tsave: Flags.boolean({\n\t\tchar: 's',\n\t\tdescription: 'Save report to default reports folder on disk',\n\t\texclusive: ['save-to-file-path'],\n\t}),\n\t'save-to-file-path': Flags.string({\n\t\tdescription: 'Override default file path to save report',\n\t\texclusive: ['save'],\n\t\tparse: utils.parsePath,\n\t}),\n\tfields: Flags.string({\n\t\tdescription: 'Comma separated list of fields to show',\n\t}),\n\t'bulk-file-path': Flags.string({\n\t\tdescription: 'File path to bulk .csv or .json objects',\n\t\tparse: utils.parsePath,\n\t}),\n\thelp: Flags.help({\n\t\tchar: 'h',\n\t\tdescription: 'Show CLI help',\n\t}),\n\tverbose: Flags.boolean({\n\t\tchar: 'v',\n\t\tdescription: 'Show verbose output, which can be helpful for debugging',\n\t}),\n\tyes: Flags.boolean({\n\t\tchar: 'y',\n\t\tdescription: 'Automatically respond yes to all confirmation prompts',\n\t}),\n\tquiet: Flags.boolean({\n\t\tchar: 'q',\n\t\tdescription: 'Suppress any non-error output to stderr',\n\t}),\n};\n\nBoxCommand.rawJsonFlags = Object.freeze({\n\t'raw-json': Flags.boolean({\n\t\tdescription:\n\t\t\t'Output the raw API JSON response instead of the tsClient-normalized object fields. Added as a non-breaking compatibility flag for users who need JSON field names to match the API schema exactly. Implies --json.',\n\t\texclusive: ['csv'],\n\t}),\n});\n\nBoxCommand.minFlags = _.pick(BoxCommand.flags, [\n\t'no-color',\n\t'help',\n\t'verbose',\n\t'quiet',\n]);\n\nmodule.exports = BoxCommand;\n"
  },
  {
    "path": "src/cli-error.js",
    "content": "'use strict';\n\nconst os = require('node:os');\n\n/**\n * Wrapper for lower-level errors, so we can give reasonable error messages without losing the original message/stack\n * This error deliberately elides its own stack trace; it is intended to be directly displayed to users\n */\nclass BoxCLIError extends Error {\n\t/**\n\t * Create the wrapped error\n\t *\n\t * @param {string} message Error message\n\t * @param {Error} [cause] The lower-level error that caused this error\n\t * @constructor\n\t */\n\tconstructor(message, cause) {\n\t\tsuper(message);\n\t\tthis.name = 'BoxCLIError';\n\t\tthis.cause = cause;\n\n\t\tif (cause) {\n\t\t\tthis.stack = `${this.name}: ${this.message}${os.EOL}Caused by: ${cause.stack}`;\n\t\t}\n\t}\n}\n\nmodule.exports = BoxCLIError;\n"
  },
  {
    "path": "src/commands/.eslintrc.yml",
    "content": "rules:\n    # Most commands are classes with just a run method that don't need documentation\n    require-jsdoc:\n      - error\n      - \n          require:\n              ClassDeclaration: false\n              MethodDefinition: false\n    # `flags` is currently shadowed in most commands, not a big deal\n    no-shadow:\n        - error\n        - \n            allow:\n                - flags\n"
  },
  {
    "path": "src/commands/ai/ask.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass AiAskCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(AiAskCommand);\n\t\tlet options = {\n\t\t\tmode:\n\t\t\t\tflags.items.length > 1 ? 'multiple_item_qa' : 'single_item_qa',\n\t\t};\n\n\t\tif (flags.prompt) {\n\t\t\toptions.prompt = flags.prompt;\n\t\t}\n\t\tif (flags.items) {\n\t\t\toptions.items = flags.items;\n\t\t}\n\t\tif (flags['ai-agent']) {\n\t\t\toptions.aiAgent = flags['ai-agent'];\n\t\t}\n\n\t\tlet answer = await this.tsClient.ai.createAiAsk(options);\n\t\tawait this.output(this.getOutputContentWithRawJsonSupport(answer));\n\t}\n}\n\nAiAskCommand.description =\n\t'Sends a request to supported LLMs using Box AI. This is intended for direct use, not by AI agents.';\nAiAskCommand.examples = [\n\t'box ai:ask --items=id=12345,type=file --prompt \"What is the status of this document?\"',\n];\nAiAskCommand._endpoint = 'post_ai_ask';\n\nAiAskCommand.flags = {\n\t...BoxCommand.flags,\n\tprompt: Flags.string({\n\t\trequired: true,\n\t\tdescription: 'The prompt for the AI request',\n\t}),\n\titems: Flags.string({\n\t\trequired: true,\n\t\tdescription:\n\t\t\t'Items for the AI request. Format: id=FILE_ID,type=file (or content=TEXT,type=file). Supported keys: id, type, content.',\n\t\tmultiple: true,\n\t\tparse(input) {\n\t\t\tconst item = {\n\t\t\t\tid: '',\n\t\t\t\ttype: 'file',\n\t\t\t};\n\t\t\tconst object = utilities.parseStringToObject(input, [\n\t\t\t\t'id',\n\t\t\t\t'type',\n\t\t\t\t'content',\n\t\t\t]);\n\t\t\tfor (const key in object) {\n\t\t\t\tswitch (key) {\n\t\t\t\t\tcase 'id': {\n\t\t\t\t\t\titem.id = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'type': {\n\t\t\t\t\t\titem.type = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'content': {\n\t\t\t\t\t\titem.content = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tthrow new Error(`Invalid item key ${key}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn item;\n\t\t},\n\t}),\n\t'ai-agent': Flags.string({\n\t\trequired: false,\n\t\tdescription:\n\t\t\t'AI agent configuration as JSON. Example: {\"type\":\"ai_agent_ask\",\"basic_text\":{\"model\":\"azure__openai__gpt_4o_mini\"}}',\n\t\tparse(input) {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(input);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Error parsing AI agent JSON: ${error.message}`\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t}),\n\t...BoxCommand.rawJsonFlags,\n};\n\nmodule.exports = AiAskCommand;\n"
  },
  {
    "path": "src/commands/ai/extract-structured.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass AiExtractStructuredCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(AiExtractStructuredCommand);\n\t\tlet options = {};\n\n\t\tif (flags.items) {\n\t\t\toptions.items = flags.items;\n\t\t}\n\n\t\tif (flags.fields && flags['metadata-template']) {\n\t\t\tthrow new Error(\n\t\t\t\t'Only one of fields or metadata_template can be provided'\n\t\t\t);\n\t\t}\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t\tdelete this.flags.fields;\n\t\t} else if (flags['metadata-template']) {\n\t\t\toptions.metadataTemplate = flags['metadata-template'];\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t'Either fields or metadata_template must be provided'\n\t\t\t);\n\t\t}\n\n\t\tif (flags['ai-agent']) {\n\t\t\toptions.aiAgent = flags['ai-agent'];\n\t\t}\n\n\t\tlet answer = await this.tsClient.ai.createAiExtractStructured(options);\n\n\t\tawait this.output(answer.rawData);\n\t}\n}\n\nAiExtractStructuredCommand.description =\n\t'Sends an AI request to supported Large Language Models (LLMs) and returns extracted metadata as a set of key-value pairs. For this request, you either need a metadata template or a list of fields you want to extract. Input is either a metadata template or a list of fields to ensure the structure. This is intended for direct use, not by AI agents.';\nAiExtractStructuredCommand.examples = [\n\t'box ai:extract-structured --items=\"id=12345,type=file\" --fields \"key=hobby,type=multiSelect,description=Person hobby,prompt=What is your hobby?,displayName=Hobby,options=Guitar;Books\"',\n\t'box ai:extract-structured --items=\"id=12345,type=file\" --metadata-template=\"type=metadata_template,scope=enterprise,template_key=test\" --ai-agent \\'{\"type\":\"ai_agent_extract_structured\",\"basic_text\":{\"model\":\"azure__openai__gpt_4o_mini\",\"prompt_template\":\"Answer using the provided content\"}}\\'',\n];\nAiExtractStructuredCommand._endpoint = 'post_ai_extract_structured';\n\nAiExtractStructuredCommand.flags = {\n\t...BoxCommand.flags,\n\titems: Flags.string({\n\t\trequired: true,\n\t\tdescription:\n\t\t\t'Items for structured extraction. Format: id=FILE_ID,type=file (or content=TEXT,type=file). Supported keys: id, type, content.',\n\t\tmultiple: true,\n\t\tparse(input) {\n\t\t\tconst item = {\n\t\t\t\tid: '',\n\t\t\t\ttype: 'file',\n\t\t\t};\n\t\t\tconst object = utilities.parseStringToObject(input, [\n\t\t\t\t'id',\n\t\t\t\t'type',\n\t\t\t\t'content',\n\t\t\t]);\n\t\t\tfor (const key in object) {\n\t\t\t\tswitch (key) {\n\t\t\t\t\tcase 'id': {\n\t\t\t\t\t\titem.id = object[key];\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'type': {\n\t\t\t\t\t\titem.type = object[key];\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'content': {\n\t\t\t\t\t\titem.content = object[key];\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tthrow new Error(`Invalid item key ${key}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (!item.id) {\n\t\t\t\tthrow new Error('Item must include an id');\n\t\t\t}\n\t\t\treturn item;\n\t\t},\n\t}),\n\t'metadata-template': Flags.string({\n\t\tdescription: 'The metadata template containing the fields to extract.',\n\t\tparse(input) {\n\t\t\tconst metadataTemplate = {\n\t\t\t\ttype: 'metadata_template',\n\t\t\t\tscope: '',\n\t\t\t\ttemplateKey: '',\n\t\t\t};\n\t\t\tconst object = utilities.parseStringToObject(input, [\n\t\t\t\t'type',\n\t\t\t\t'scope',\n\t\t\t\t'template_key',\n\t\t\t]);\n\t\t\tfor (const key in object) {\n\t\t\t\tswitch (key) {\n\t\t\t\t\tcase 'type': {\n\t\t\t\t\t\tmetadataTemplate.type = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'scope': {\n\t\t\t\t\t\tmetadataTemplate.scope = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'template_key': {\n\t\t\t\t\t\tmetadataTemplate.templateKey = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tthrow new Error(`Invalid item key ${key}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn metadataTemplate;\n\t\t},\n\t}),\n\tfields: Flags.string({\n\t\tmultiple: true,\n\t\tdescription:\n\t\t\t'Fields to extract from the provided items. Use options=VALUE1;VALUE2 for multiSelect fields.',\n\t\tparse(input) {\n\t\t\tconst fields = {};\n\t\t\tconst object = utilities.parseStringToObject(input, [\n\t\t\t\t'key',\n\t\t\t\t'type',\n\t\t\t\t'description',\n\t\t\t\t'prompt',\n\t\t\t\t'displayName',\n\t\t\t\t'options',\n\t\t\t]);\n\t\t\tfor (const key in object) {\n\t\t\t\tswitch (key) {\n\t\t\t\t\tcase 'key': {\n\t\t\t\t\t\tfields.key = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'type': {\n\t\t\t\t\t\tfields.type = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'description': {\n\t\t\t\t\t\tfields.description = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'prompt': {\n\t\t\t\t\t\tfields.prompt = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'displayName': {\n\t\t\t\t\t\tfields.displayName = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'options': {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst parsedOptions = object[key]\n\t\t\t\t\t\t\t\t.split(';')\n\t\t\t\t\t\t\t\t.filter(Boolean)\n\t\t\t\t\t\t\t\t.map((item) => ({ key: item.trim() }));\n\t\t\t\t\t\t\tif (parsedOptions.length === 0) {\n\t\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t\t'Options field must contain at least one value'\n\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tfields.options = parsedOptions;\n\t\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t\t\t`Error parsing options: ${error.message}`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tthrow new Error(`Invalid item key ${key}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn fields;\n\t\t},\n\t}),\n\t'ai-agent': Flags.string({\n\t\trequired: false,\n\t\tdescription:\n\t\t\t'AI agent configuration as JSON. Example: {\"type\":\"ai_agent_extract_structured\",\"basic_text\":{\"model\":\"azure__openai__gpt_4o_mini\",\"prompt_template\":\"Answer the question based on {content}\"}}',\n\t\tparse(input) {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(input);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Error parsing AI agent JSON: ${error.message}`\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t}),\n};\n\nmodule.exports = AiExtractStructuredCommand;\n"
  },
  {
    "path": "src/commands/ai/extract.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass AiExtractCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(AiExtractCommand);\n\t\tlet options = {};\n\n\t\tif (flags.prompt) {\n\t\t\toptions.prompt = flags.prompt;\n\t\t}\n\t\tif (flags.items) {\n\t\t\toptions.items = flags.items;\n\t\t}\n\t\tif (flags['ai-agent']) {\n\t\t\toptions.aiAgent = flags['ai-agent'];\n\t\t}\n\n\t\tlet answer = await this.tsClient.ai.createAiExtract(options);\n\t\tawait this.output(this.getOutputContentWithRawJsonSupport(answer));\n\t}\n}\n\nAiExtractCommand.description =\n\t'Sends an AI request to supported Large Language Models (LLMs) and extracts metadata in form of key-value pairs. This is intended for direct use, not by AI agents.';\nAiExtractCommand.examples = [\n\t'box ai:extract --items=id=12345,type=file --prompt \"firstName, lastName, location, yearOfBirth, company\"',\n\t'box ai:extract --prompt \"firstName, lastName, location, yearOfBirth, company\" --items \"id=12345,type=file\" --ai-agent \\'{\"type\":\"ai_agent_extract\",\"basic_text\":{\"model\":\"azure__openai__gpt_4o_mini\"}}\\'',\n];\nAiExtractCommand._endpoint = 'post_ai_extract';\n\n// Flags definition\nAiExtractCommand.flags = {\n\t...BoxCommand.flags,\n\t...BoxCommand.rawJsonFlags,\n\tprompt: Flags.string({\n\t\trequired: true,\n\t\tdescription:\n\t\t\t'The prompt provided to a Large Language Model (LLM) in the request.',\n\t}),\n\titems: Flags.string({\n\t\trequired: true,\n\t\tdescription:\n\t\t\t'Items for extraction. Format: id=FILE_ID,type=file (or content=TEXT,type=file). Supported keys: id, type, content.',\n\t\tmultiple: true,\n\t\tparse(input) {\n\t\t\tconst item = {\n\t\t\t\tid: '',\n\t\t\t\ttype: 'file',\n\t\t\t};\n\n\t\t\tconst object = utilities.parseStringToObject(input, [\n\t\t\t\t'id',\n\t\t\t\t'type',\n\t\t\t\t'content',\n\t\t\t]);\n\t\t\tfor (const key in object) {\n\t\t\t\tswitch (key) {\n\t\t\t\t\tcase 'id': {\n\t\t\t\t\t\titem.id = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'type': {\n\t\t\t\t\t\titem.type = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'content': {\n\t\t\t\t\t\titem.content = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tthrow new Error(`Invalid item key ${key}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn item;\n\t\t},\n\t}),\n\t'ai-agent': Flags.string({\n\t\trequired: false,\n\t\tdescription:\n\t\t\t'AI agent configuration as JSON. Example: {\"type\":\"ai_agent_extract\",\"basic_text\":{\"model\":\"azure__openai__gpt_4o_mini\",\"prompt_template\":\"Answer the question based on {content}\"}}',\n\t\tparse(input) {\n\t\t\ttry {\n\t\t\t\treturn JSON.parse(input);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Error parsing AI agent JSON: ${error.message}`\n\t\t\t\t);\n\t\t\t}\n\t\t},\n\t}),\n};\n\nmodule.exports = AiExtractCommand;\n"
  },
  {
    "path": "src/commands/ai/text-gen.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass AiTextGenCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(AiTextGenCommand);\n\t\tlet options = {};\n\n\t\tif (flags['dialogue-history']) {\n\t\t\toptions.dialogueHistory = flags['dialogue-history'];\n\t\t}\n\t\toptions.prompt = flags.prompt;\n\t\toptions.items = flags.items;\n\n\t\tlet answer = await this.client.ai.textGen({\n\t\t\tprompt: options.prompt,\n\t\t\titems: options.items,\n\t\t\tdialogue_history: options.dialogueHistory,\n\t\t});\n\n\t\tawait this.output(answer);\n\t}\n}\n\nAiTextGenCommand.description =\n\t'Sends an AI request to supported LLMs and returns an answer specifically focused on the creation of new text. This is intended for direct use, not by AI agents.';\nAiTextGenCommand.examples = [\n\t'box ai:text-gen --dialogue-history=prompt=\"What is the status of this document?\",answer=\"It is in review\",created-at=\"2024-07-09T11:29:46.835Z\" --items=id=12345,type=file --prompt=\"What is the status of this document?\"',\n];\nAiTextGenCommand._endpoint = 'post_ai_text_gen';\n\nAiTextGenCommand.flags = {\n\t...BoxCommand.flags,\n\n\t'dialogue-history': Flags.string({\n\t\trequired: false,\n\t\tdescription:\n\t\t\t'The history of prompts and answers previously passed to the LLM.',\n\t\tmultiple: true,\n\t\tparse(input) {\n\t\t\tconst record = {};\n\t\t\tconst object = utilities.parseStringToObject(input, [\n\t\t\t\t'prompt',\n\t\t\t\t'answer',\n\t\t\t\t'created-at',\n\t\t\t]);\n\t\t\tfor (const key in object) {\n\t\t\t\tswitch (key) {\n\t\t\t\t\tcase 'prompt': {\n\t\t\t\t\t\trecord.prompt = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'answer': {\n\t\t\t\t\t\trecord.answer = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'created-at': {\n\t\t\t\t\t\trecord.created_at = BoxCommand.normalizeDateString(\n\t\t\t\t\t\t\tobject[key]\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tthrow new Error(`Invalid record key ${key}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn record;\n\t\t},\n\t}),\n\titems: Flags.string({\n\t\trequired: true,\n\t\tdescription:\n\t\t\t'Items for text generation. Format: id=FILE_ID,type=file (or content=TEXT,type=file). Supported keys: id, type, content. Exactly one item is supported.',\n\t\tmultiple: true,\n\t\tparse(input) {\n\t\t\tconst item = {\n\t\t\t\tid: '',\n\t\t\t\ttype: 'file',\n\t\t\t};\n\t\t\tconst object = utilities.parseStringToObject(input, [\n\t\t\t\t'id',\n\t\t\t\t'type',\n\t\t\t\t'content',\n\t\t\t]);\n\t\t\tfor (const key in object) {\n\t\t\t\tswitch (key) {\n\t\t\t\t\tcase 'id': {\n\t\t\t\t\t\titem.id = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'type': {\n\t\t\t\t\t\titem.type = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tcase 'content': {\n\t\t\t\t\t\titem.content = object[key];\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tthrow new Error(`Invalid item key ${key}`);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn item;\n\t\t},\n\t}),\n\tprompt: Flags.string({\n\t\trequired: true,\n\t\tdescription: 'The prompt for the AI request',\n\t}),\n};\n\nmodule.exports = AiTextGenCommand;\n"
  },
  {
    "path": "src/commands/collaboration-allowlist/add.js",
    "content": "'use strict';\n\nconst { Flags, Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass CollaborationAllowlistAddCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tCollaborationAllowlistAddCommand\n\t\t);\n\n\t\tlet allowlistEntry = await this.client.collaborationAllowlist.addDomain(\n\t\t\targs.domain,\n\t\t\tflags.direction\n\t\t);\n\t\tawait this.output(allowlistEntry);\n\t}\n}\n\nCollaborationAllowlistAddCommand.description =\n\t'Add a collaboration allowlist entry';\nCollaborationAllowlistAddCommand.examples = [\n\t'box collaboration-allowlist:add example.com --direction outbound',\n];\nCollaborationAllowlistAddCommand._endpoint =\n\t'post_collaboration_whitelist_entries';\n\nCollaborationAllowlistAddCommand.flags = {\n\t...BoxCommand.flags,\n\tdirection: Flags.string({\n\t\tdescription: 'Direction to allowlist collaboration in',\n\t\toptions: ['inbound', 'outbound', 'both'],\n\t\trequired: true,\n\t}),\n};\n\nCollaborationAllowlistAddCommand.args = {\n\tdomain: Args.string({\n\t\tname: 'domain',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Domain to add to allowlist (e.g. box.com)',\n\t}),\n};\n\nmodule.exports = CollaborationAllowlistAddCommand;\n"
  },
  {
    "path": "src/commands/collaboration-allowlist/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass CollaborationAllowlistDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(CollaborationAllowlistDeleteCommand);\n\n\t\tawait this.client.collaborationAllowlist.removeDomain(args.id);\n\t\tthis.info(`Deleted collaboration allowlist entry ${args.id}`);\n\t}\n}\n\nCollaborationAllowlistDeleteCommand.description =\n\t'Delete a collaboration allowlist entry';\nCollaborationAllowlistDeleteCommand.examples = [\n\t'box collaboration-allowlist:delete 12345',\n];\nCollaborationAllowlistDeleteCommand._endpoint =\n\t'delete_collaboration_whitelist_entries_id';\n\nCollaborationAllowlistDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nCollaborationAllowlistDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the collaboration allowlist entry record to delete',\n\t}),\n};\n\nmodule.exports = CollaborationAllowlistDeleteCommand;\n"
  },
  {
    "path": "src/commands/collaboration-allowlist/exemptions/create.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass CollaborationAllowlistCreateExemptionCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(\n\t\t\tCollaborationAllowlistCreateExemptionCommand\n\t\t);\n\n\t\tlet exemptEntry = await this.client.collaborationAllowlist.addExemption(\n\t\t\targs.userID\n\t\t);\n\t\tawait this.output(exemptEntry);\n\t}\n}\n\nCollaborationAllowlistCreateExemptionCommand.description =\n\t'Exempt a user from the collaboration allowlist';\nCollaborationAllowlistCreateExemptionCommand.examples = [\n\t'box collaboration-allowlist:exemptions:create 11111',\n];\nCollaborationAllowlistCreateExemptionCommand._endpoint =\n\t'post_collaboration_whitelist_exempt_targets';\n\nCollaborationAllowlistCreateExemptionCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nCollaborationAllowlistCreateExemptionCommand.args = {\n\tuserID: Args.string({\n\t\tname: 'userID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription:\n\t\t\t'ID of the user to exempt from the collaboration allowlist',\n\t}),\n};\n\nmodule.exports = CollaborationAllowlistCreateExemptionCommand;\n"
  },
  {
    "path": "src/commands/collaboration-allowlist/exemptions/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass CollaborationAllowlistDeleteExemptionCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(\n\t\t\tCollaborationAllowlistDeleteExemptionCommand\n\t\t);\n\n\t\tawait this.client.collaborationAllowlist.removeExemption(args.id);\n\t\tthis.info(`Deleted collaboration allowlist exemption ${args.id}`);\n\t}\n}\n\nCollaborationAllowlistDeleteExemptionCommand.description =\n\t'Delete a collaboration allowlist exemption';\nCollaborationAllowlistDeleteExemptionCommand.examples = [\n\t'box collaboration-allowlist:exemptions:delete 12345',\n];\nCollaborationAllowlistDeleteExemptionCommand._endpoint =\n\t'delete_collaboration_whitelist_exempt_targets_id';\n\nCollaborationAllowlistDeleteExemptionCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nCollaborationAllowlistDeleteExemptionCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the allowlist exemption record to delete',\n\t}),\n};\n\nmodule.exports = CollaborationAllowlistDeleteExemptionCommand;\n"
  },
  {
    "path": "src/commands/collaboration-allowlist/exemptions/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass CollaborationAllowlistGetExemptionCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tCollaborationAllowlistGetExemptionCommand\n\t\t);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet exemption = await this.client.collaborationAllowlist.getExemption(\n\t\t\targs.id,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(exemption);\n\t}\n}\n\nCollaborationAllowlistGetExemptionCommand.description =\n\t'Get a collaboration allowlist exemption';\nCollaborationAllowlistGetExemptionCommand.examples = [\n\t'box collaboration-allowlist:exemptions:get 12345',\n];\nCollaborationAllowlistGetExemptionCommand._endpoint =\n\t'get_collaboration_whitelist_exempt_targets_id';\n\nCollaborationAllowlistGetExemptionCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nCollaborationAllowlistGetExemptionCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the allowlist exemption record to get',\n\t}),\n};\n\nmodule.exports = CollaborationAllowlistGetExemptionCommand;\n"
  },
  {
    "path": "src/commands/collaboration-allowlist/exemptions/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst PaginationUtilities = require('../../../pagination-utils');\n\nclass CollaborationAllowlistListExemptUserCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(\n\t\t\tCollaborationAllowlistListExemptUserCommand\n\t\t);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet exemptions =\n\t\t\tawait this.client.collaborationAllowlist.getAllExemptions(options);\n\t\tawait this.output(exemptions);\n\t}\n}\n\nCollaborationAllowlistListExemptUserCommand.description =\n\t'List collaboration allowlist exemptions';\nCollaborationAllowlistListExemptUserCommand.examples = [\n\t'box collaboration-allowlist:exemptions',\n];\nCollaborationAllowlistListExemptUserCommand._endpoint =\n\t'get_collaboration_whitelist_exempt_targets';\n\nCollaborationAllowlistListExemptUserCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nmodule.exports = CollaborationAllowlistListExemptUserCommand;\n"
  },
  {
    "path": "src/commands/collaboration-allowlist/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass CollaborationAllowlistGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tCollaborationAllowlistGetCommand\n\t\t);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet allowlistEntry =\n\t\t\tawait this.client.collaborationAllowlist.getAllowlistedDomain(\n\t\t\t\targs.id,\n\t\t\t\toptions\n\t\t\t);\n\t\tawait this.output(allowlistEntry);\n\t}\n}\n\nCollaborationAllowlistGetCommand.description =\n\t'Get a collaboration allowlist entry';\nCollaborationAllowlistGetCommand.examples = [\n\t'box collaboration-allowlist:get 12345',\n];\nCollaborationAllowlistGetCommand._endpoint =\n\t'get_collaboration_whitelist_entries_id';\n\nCollaborationAllowlistGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nCollaborationAllowlistGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the collaboration allowlist entry record to get',\n\t}),\n};\n\nmodule.exports = CollaborationAllowlistGetCommand;\n"
  },
  {
    "path": "src/commands/collaboration-allowlist/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass CollaborationAllowlistListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(CollaborationAllowlistListCommand);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet allowlistEntries =\n\t\t\tawait this.client.collaborationAllowlist.getAllAllowlistedDomains(\n\t\t\t\toptions\n\t\t\t);\n\t\tawait this.output(allowlistEntries);\n\t}\n}\n\nCollaborationAllowlistListCommand.description =\n\t'List collaboration allowlist entries';\nCollaborationAllowlistListCommand.examples = ['box collaboration-allowlist'];\nCollaborationAllowlistListCommand._endpoint =\n\t'get_collaboration_whitelist_entries';\n\nCollaborationAllowlistListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nmodule.exports = CollaborationAllowlistListCommand;\n"
  },
  {
    "path": "src/commands/collaboration-whitelist/index.js",
    "content": "'use strict';\n\nconst CollaborationAllowlistListCommand = require('../collaboration-allowlist');\n\nclass CollaborationWhitelistListCommand extends CollaborationAllowlistListCommand {}\n\nfor (const name of ['description', 'examples', '_endpoint', 'flags']) {\n\tCollaborationWhitelistListCommand[name] =\n\t\tCollaborationAllowlistListCommand[name];\n}\n\nCollaborationWhitelistListCommand.hidden = true;\n\nmodule.exports = CollaborationWhitelistListCommand;\n"
  },
  {
    "path": "src/commands/collaborations/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst CollaborationModule = require('../../modules/collaboration');\n\nclass CollaborationsAddCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(CollaborationsAddCommand);\n\n\t\tlet collabModule = new CollaborationModule(this.client);\n\t\tlet collaboration = await collabModule.createCollaboration(args, flags);\n\t\tawait this.output(collaboration);\n\t}\n}\n\nCollaborationsAddCommand.aliases = ['collaborations:add'];\n\nCollaborationsAddCommand.description = 'Create a collaboration for a Box item';\nCollaborationsAddCommand.examples = [\n\t'box collaborations:create 22222 folder --role editor --user-id 33333',\n];\nCollaborationsAddCommand._endpoint = 'post_collaborations';\n\nCollaborationsAddCommand.flags = {\n\t...BoxCommand.flags,\n\trole: Flags.string({\n\t\tchar: 'r',\n\t\tdescription: 'An option to manually enter the role',\n\t\texclusive: [\n\t\t\t'editor',\n\t\t\t'viewer',\n\t\t\t'previewer',\n\t\t\t'uploader',\n\t\t\t'previewer-uploader',\n\t\t\t'viewer-uploader',\n\t\t\t'co-owner',\n\t\t],\n\t\toptions: [\n\t\t\t'editor',\n\t\t\t'viewer',\n\t\t\t'previewer',\n\t\t\t'uploader',\n\t\t\t'previewer_uploader',\n\t\t\t'viewer_uploader',\n\t\t\t'co-owner',\n\t\t],\n\t}),\n\t'user-id': Flags.string({\n\t\tdescription: 'Id for user to collaborate',\n\t\texclusive: ['group-id', 'login'],\n\t}),\n\t'group-id': Flags.string({\n\t\tdescription: 'Id for group to collaborate',\n\t\texclusive: ['user-id', 'login'],\n\t}),\n\tlogin: Flags.string({\n\t\tdescription: 'Login for user to collaborate',\n\t\texclusive: ['group-id', 'user-id'],\n\t}),\n\teditor: Flags.boolean({\n\t\tdescription: 'Set the role to editor',\n\t\thidden: true,\n\t\texclusive: [\n\t\t\t'role',\n\t\t\t'viewer',\n\t\t\t'previewer',\n\t\t\t'uploader',\n\t\t\t'previewer-uploader',\n\t\t\t'viewer-uploader',\n\t\t\t'co-owner',\n\t\t],\n\t}),\n\tviewer: Flags.boolean({\n\t\tdescription: 'Set the role to viewer',\n\t\thidden: true,\n\t\texclusive: [\n\t\t\t'role',\n\t\t\t'editor',\n\t\t\t'previewer',\n\t\t\t'uploader',\n\t\t\t'previewer-uploader',\n\t\t\t'viewer-uploader',\n\t\t\t'co-owner',\n\t\t],\n\t}),\n\tpreviewer: Flags.boolean({\n\t\tdescription: 'Set the role to previewer',\n\t\thidden: true,\n\t\texclusive: [\n\t\t\t'role',\n\t\t\t'viewer',\n\t\t\t'editor',\n\t\t\t'uploader',\n\t\t\t'previewer-uploader',\n\t\t\t'viewer-uploader',\n\t\t\t'co-owner',\n\t\t],\n\t}),\n\tuploader: Flags.boolean({\n\t\tdescription: 'Set the role to uploader',\n\t\thidden: true,\n\t\texclusive: [\n\t\t\t'role',\n\t\t\t'viewer',\n\t\t\t'previewer',\n\t\t\t'editor',\n\t\t\t'previewer-uploader',\n\t\t\t'viewer-uploader',\n\t\t\t'co-owner',\n\t\t],\n\t}),\n\t'previewer-uploader': Flags.boolean({\n\t\tdescription: 'Set the role to previewer-uploader',\n\t\thidden: true,\n\t\texclusive: [\n\t\t\t'role',\n\t\t\t'viewer',\n\t\t\t'previewer',\n\t\t\t'uploader',\n\t\t\t'editor',\n\t\t\t'viewer-uploader',\n\t\t\t'co-owner',\n\t\t],\n\t}),\n\t'viewer-uploader': Flags.boolean({\n\t\tdescription: 'Set the role to viewer-uploader',\n\t\thidden: true,\n\t\texclusive: [\n\t\t\t'role',\n\t\t\t'viewer',\n\t\t\t'previewer',\n\t\t\t'uploader',\n\t\t\t'previewer-uploader',\n\t\t\t'editor',\n\t\t\t'co-owner',\n\t\t],\n\t}),\n\t'co-owner': Flags.boolean({\n\t\tdescription: 'Set the role to co-owner',\n\t\thidden: true,\n\t\texclusive: [\n\t\t\t'role',\n\t\t\t'viewer',\n\t\t\t'previewer',\n\t\t\t'uploader',\n\t\t\t'previewer-uploader',\n\t\t\t'viewer-uploader',\n\t\t\t'editor',\n\t\t],\n\t}),\n\t'can-view-path': Flags.boolean({\n\t\tdescription:\n\t\t\t'Whether view path collaboration feature is enabled or not',\n\t\tallowNo: true,\n\t}),\n\t'id-only': Flags.boolean({\n\t\tdescription: 'Return only an ID to output from this command',\n\t}),\n\tnotify: Flags.boolean({\n\t\tdescription:\n\t\t\t'All users will receive email notification of the collaboration',\n\t\tallowNo: true,\n\t}),\n};\n\nCollaborationsAddCommand.args = {\n\titemID: Args.string({\n\t\tname: 'itemID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The ID of the Box item to add the collaboration to',\n\t}),\n\titemType: Args.string({\n\t\tname: 'itemType',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The type of the Box item to add the collaboration to',\n\t\toptions: ['file', 'folder'],\n\t}),\n};\n\nmodule.exports = CollaborationsAddCommand;\n"
  },
  {
    "path": "src/commands/collaborations/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass CollaborationsDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(CollaborationsDeleteCommand);\n\n\t\tawait this.client.collaborations.delete(args.id);\n\t\tthis.info(`Collaboration ${args.id} successfully removed`);\n\t}\n}\n\nCollaborationsDeleteCommand.aliases = [\n\t'files:collaborations:delete',\n\t'folders:collaborations:delete',\n];\n\nCollaborationsDeleteCommand.description = 'Remove a collaboration';\nCollaborationsDeleteCommand.examples = ['box collaborations:delete 12345'];\nCollaborationsDeleteCommand._endpoint = 'delete_collaborations_id';\n\nCollaborationsDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nCollaborationsDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The ID of the collaboration to delete',\n\t}),\n};\n\nmodule.exports = CollaborationsDeleteCommand;\n"
  },
  {
    "path": "src/commands/collaborations/get.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Args } = require('@oclif/core');\n\nclass CollaborationsGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(CollaborationsGetCommand);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet collaboration = await this.client.collaborations.get(\n\t\t\targs.id,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(collaboration);\n\t}\n}\n\nCollaborationsGetCommand.description = 'Get an individual collaboration';\nCollaborationsGetCommand.examples = ['box collaborations:get 12345'];\nCollaborationsGetCommand._endpoint = 'get_collaborations_id';\n\nCollaborationsGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nCollaborationsGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the collaboration to get',\n\t}),\n};\n\nmodule.exports = CollaborationsGetCommand;\n"
  },
  {
    "path": "src/commands/collaborations/pending.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass CollaborationsGetPendingCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(CollaborationsGetPendingCommand);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\t\tlet parameters = {\n\t\t\tqs: {\n\t\t\t\tstatus: 'pending',\n\t\t\t\tlimit: options.limit,\n\t\t\t},\n\t\t};\n\n\t\tif (flags.fields) {\n\t\t\tparameters.qs.fields = flags.fields;\n\t\t}\n\n\t\t// @TODO (2018-07-07): Should implement this using the Node SDK\n\t\tlet collaborations = await this.client.wrapWithDefaultHandler(\n\t\t\tthis.client.get\n\t\t)('/collaborations', parameters);\n\t\tawait this.output(collaborations);\n\t}\n}\n\nCollaborationsGetPendingCommand.aliases = ['collaborations:get-pending'];\n\nCollaborationsGetPendingCommand.description =\n\t'List all pending collaborations for a user';\nCollaborationsGetPendingCommand.examples = ['box collaborations:pending'];\nCollaborationsGetPendingCommand._endpoint = 'get_collaborations pending';\n\nCollaborationsGetPendingCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nmodule.exports = CollaborationsGetPendingCommand;\n"
  },
  {
    "path": "src/commands/collaborations/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst chalk = require('chalk');\n\nclass CollaborationsUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(CollaborationsUpdateCommand);\n\t\tlet parameters = { body: {}, qs: {} };\n\n\t\tif (flags.fields) {\n\t\t\tparameters.qs.fields = flags.fields;\n\t\t}\n\t\tif (flags.status) {\n\t\t\tparameters.body.status = flags.status;\n\t\t}\n\t\tif (Object.hasOwn(flags, 'can-view-path')) {\n\t\t\tparameters.body.can_view_path = flags['can-view-path'];\n\t\t}\n\t\tif (flags.role) {\n\t\t\tparameters.body.role = flags.role.replace('_', ' ');\n\t\t} else if (flags.editor) {\n\t\t\tparameters.body.role = this.client.collaborationRoles.EDITOR;\n\t\t} else if (flags.viewer) {\n\t\t\tparameters.body.role = this.client.collaborationRoles.VIEWER;\n\t\t} else if (flags.previewer) {\n\t\t\tparameters.body.role = this.client.collaborationRoles.PREVIEWER;\n\t\t} else if (flags.uploader) {\n\t\t\tparameters.body.role = this.client.collaborationRoles.UPLOADER;\n\t\t} else if (flags['previewer-uploader']) {\n\t\t\tparameters.body.role =\n\t\t\t\tthis.client.collaborationRoles.PREVIEWER_UPLOADER;\n\t\t} else if (flags['viewer-uploader']) {\n\t\t\tparameters.body.role =\n\t\t\t\tthis.client.collaborationRoles.VIEWER_UPLOADER;\n\t\t} else if (flags['co-owner']) {\n\t\t\tparameters.body.role = this.client.collaborationRoles.CO_OWNER;\n\t\t} else if (flags.owner) {\n\t\t\tparameters.body.role = this.client.collaborationRoles.OWNER;\n\t\t}\n\t\tif (flags['expires-at']) {\n\t\t\tparameters.body.expires_at = flags['expires-at'];\n\t\t}\n\n\t\t// @TODO (2018-07-07): Should implement this using the Node SDK\n\t\tlet collaboration = await this.client.wrapWithDefaultHandler(\n\t\t\tthis.client.put\n\t\t)(`/collaborations/${args.id}`, parameters);\n\t\tif (collaboration) {\n\t\t\tawait this.output(collaboration);\n\t\t} else if (\n\t\t\tparameters.body.role === this.client.collaborationRoles.OWNER\n\t\t) {\n\t\t\t// Upgrading a collaborator to owner produces a 204 response with empty body\n\t\t\t// Output a success message instead of trying to print the updated collaboration\n\t\t\tthis.info(\n\t\t\t\tchalk`{green Collaborator successfully upgraded to owner.}`\n\t\t\t);\n\t\t}\n\t}\n}\n\nCollaborationsUpdateCommand.aliases = [\n\t'files:collaborations:update',\n\t'folders:collaborations:update',\n];\n\nCollaborationsUpdateCommand.description = 'Update a collaboration';\nCollaborationsUpdateCommand.examples = [\n\t'box collaborations:update 12345 --role viewer',\n];\nCollaborationsUpdateCommand._endpoint = 'put_collaborations_id';\n\nCollaborationsUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\trole: Flags.string({\n\t\tchar: 'r',\n\t\tdescription: 'An option to manually enter the role',\n\t\texclusive: [\n\t\t\t'editor',\n\t\t\t'viewer',\n\t\t\t'previewer',\n\t\t\t'uploader',\n\t\t\t'previewer-uploader',\n\t\t\t'viewer-uploader',\n\t\t\t'co-owner',\n\t\t\t'owner',\n\t\t],\n\t\toptions: [\n\t\t\t'editor',\n\t\t\t'viewer',\n\t\t\t'previewer',\n\t\t\t'uploader',\n\t\t\t'previewer_uploader',\n\t\t\t'viewer_uploader',\n\t\t\t'co-owner',\n\t\t\t'owner',\n\t\t],\n\t}),\n\tstatus: Flags.string({\n\t\tdescription: 'Update the collaboration status',\n\t\toptions: ['accepted', 'pending', 'rejected'],\n\t}),\n\teditor: Flags.boolean({\n\t\tdescription: 'Set the role to editor',\n\t\thidden: true,\n\t\texclusive: [\n\t\t\t'role',\n\t\t\t'viewer',\n\t\t\t'previewer',\n\t\t\t'uploader',\n\t\t\t'previewer-uploader',\n\t\t\t'viewer-uploader',\n\t\t\t'co-owner',\n\t\t\t'owner',\n\t\t],\n\t}),\n\tviewer: Flags.boolean({\n\t\tdescription: 'Set the role to viewer',\n\t\thidden: true,\n\t\texclusive: [\n\t\t\t'role',\n\t\t\t'editor',\n\t\t\t'previewer',\n\t\t\t'uploader',\n\t\t\t'previewer-uploader',\n\t\t\t'viewer-uploader',\n\t\t\t'co-owner',\n\t\t\t'owner',\n\t\t],\n\t}),\n\tpreviewer: Flags.boolean({\n\t\tdescription: 'Set the role to previewer',\n\t\thidden: true,\n\t\texclusive: [\n\t\t\t'role',\n\t\t\t'viewer',\n\t\t\t'editor',\n\t\t\t'uploader',\n\t\t\t'previewer-uploader',\n\t\t\t'viewer-uploader',\n\t\t\t'co-owner',\n\t\t\t'owner',\n\t\t],\n\t}),\n\tuploader: Flags.boolean({\n\t\tdescription: 'Set the role to uploader',\n\t\thidden: true,\n\t\texclusive: [\n\t\t\t'role',\n\t\t\t'viewer',\n\t\t\t'previewer',\n\t\t\t'editor',\n\t\t\t'previewer-uploader',\n\t\t\t'viewer-uploader',\n\t\t\t'co-owner',\n\t\t\t'owner',\n\t\t],\n\t}),\n\t'previewer-uploader': Flags.boolean({\n\t\tdescription: 'Set the role to previewer-uploader',\n\t\thidden: true,\n\t\texclusive: [\n\t\t\t'role',\n\t\t\t'viewer',\n\t\t\t'previewer',\n\t\t\t'uploader',\n\t\t\t'editor',\n\t\t\t'viewer-uploader',\n\t\t\t'co-owner',\n\t\t\t'owner',\n\t\t],\n\t}),\n\t'viewer-uploader': Flags.boolean({\n\t\tdescription: 'Set the role to viewer-uploader',\n\t\thidden: true,\n\t\texclusive: [\n\t\t\t'role',\n\t\t\t'viewer',\n\t\t\t'previewer',\n\t\t\t'uploader',\n\t\t\t'previewer-uploader',\n\t\t\t'editor',\n\t\t\t'co-owner',\n\t\t\t'owner',\n\t\t],\n\t}),\n\t'co-owner': Flags.boolean({\n\t\tdescription: 'Set the role to co-owner',\n\t\thidden: true,\n\t\texclusive: [\n\t\t\t'role',\n\t\t\t'viewer',\n\t\t\t'previewer',\n\t\t\t'uploader',\n\t\t\t'previewer-uploader',\n\t\t\t'viewer-uploader',\n\t\t\t'editor',\n\t\t\t'owner',\n\t\t],\n\t}),\n\towner: Flags.boolean({\n\t\tdescription: 'Set the role to owner',\n\t\thidden: true,\n\t\texclusive: [\n\t\t\t'role',\n\t\t\t'viewer',\n\t\t\t'previewer',\n\t\t\t'uploader',\n\t\t\t'previewer-uploader',\n\t\t\t'viewer-uploader',\n\t\t\t'editor',\n\t\t\t'co-owner',\n\t\t],\n\t}),\n\t'can-view-path': Flags.boolean({\n\t\tdescription:\n\t\t\t'Whether view path collaboration feature is enabled or not',\n\t\tallowNo: true,\n\t}),\n\t'expires-at': Flags.string({\n\t\tdescription: 'When the collaboration should expire',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n};\n\nCollaborationsUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The ID of the collaboration to update',\n\t}),\n};\n\nmodule.exports = CollaborationsUpdateCommand;\n"
  },
  {
    "path": "src/commands/collections/add.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\nconst chalk = require('chalk');\n\nclass CollectionsAddCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(CollectionsAddCommand);\n\t\tlet item;\n\n\t\tswitch (args.itemType) {\n\t\t\tcase 'file': {\n\t\t\t\titem = await this.client.files.addToCollection(\n\t\t\t\t\targs.itemID,\n\t\t\t\t\targs.collectionID\n\t\t\t\t);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'folder': {\n\t\t\t\titem = await this.client.folders.addToCollection(\n\t\t\t\t\targs.itemID,\n\t\t\t\t\targs.collectionID\n\t\t\t\t);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'web_link': {\n\t\t\t\titem = await this.client.weblinks.addToCollection(\n\t\t\t\t\targs.itemID,\n\t\t\t\t\targs.collectionID\n\t\t\t\t);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// No default\n\t\t}\n\n\t\tthis.info(\n\t\t\tchalk`{green Added ${args.itemType} \"${item.name}\" to collection ${args.collectionID}}`\n\t\t);\n\t}\n}\n\nCollectionsAddCommand.description = 'Add an item to a collection';\nCollectionsAddCommand.examples = ['box collections:add file 11111 12345'];\n\nCollectionsAddCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nCollectionsAddCommand.args = {\n\titemType: Args.string({\n\t\tname: 'itemType',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Type of item',\n\t\toptions: ['folder', 'file', 'web_link'],\n\t}),\n\titemID: Args.string({\n\t\tname: 'itemID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the of item',\n\t}),\n\tcollectionID: Args.string({\n\t\tname: 'collectionID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of collection',\n\t}),\n};\n\nmodule.exports = CollectionsAddCommand;\n"
  },
  {
    "path": "src/commands/collections/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\n\nclass CollectionsListCommand extends BoxCommand {\n\tasync run() {\n\t\tawait this.parse(CollectionsListCommand);\n\n\t\tlet collections = await this.client.collections.getAll();\n\t\tawait this.output(collections);\n\t}\n}\n\nCollectionsListCommand.aliases = ['collections:list'];\n\nCollectionsListCommand.description = 'List your collections';\nCollectionsListCommand.examples = ['box collections'];\nCollectionsListCommand._endpoint = 'get_collections';\n\nCollectionsListCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nmodule.exports = CollectionsListCommand;\n"
  },
  {
    "path": "src/commands/collections/items.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass CollectionsListItemsCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(CollectionsListItemsCommand);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet items = await this.client.collections.getItems(args.id, options);\n\t\tawait this.output(items);\n\t}\n}\n\nCollectionsListItemsCommand.description = 'Get items in a collection';\nCollectionsListItemsCommand.examples = ['box collections:items 12345'];\nCollectionsListItemsCommand._endpoint = 'get_collections_id_items';\n\nCollectionsListItemsCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nCollectionsListItemsCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the collection to retrieve the items of',\n\t}),\n};\n\nmodule.exports = CollectionsListItemsCommand;\n"
  },
  {
    "path": "src/commands/collections/remove.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\nconst chalk = require('chalk');\n\nclass CollectionsRemoveCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(CollectionsRemoveCommand);\n\t\tlet item;\n\n\t\tif (args.itemType === 'file') {\n\t\t\titem = await this.client.files.removeFromCollection(\n\t\t\t\targs.itemID,\n\t\t\t\targs.collectionID\n\t\t\t);\n\t\t} else if (args.itemType === 'folder') {\n\t\t\titem = await this.client.folders.removeFromCollection(\n\t\t\t\targs.itemID,\n\t\t\t\targs.collectionID\n\t\t\t);\n\t\t}\n\t\tthis.info(\n\t\t\tchalk`{green Removed ${args.itemType} \"${item.name}\" from collection ${args.collectionID}}`\n\t\t);\n\t}\n}\n\nCollectionsRemoveCommand.description = 'Remove an item from a collection';\nCollectionsRemoveCommand.examples = ['box collections:remove file 11111 12345'];\n\nCollectionsRemoveCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nCollectionsRemoveCommand.args = {\n\titemType: Args.string({\n\t\tname: 'itemType',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Type of item',\n\t\toptions: ['folder', 'file'],\n\t}),\n\titemID: Args.string({\n\t\tname: 'itemID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of item',\n\t}),\n\tcollectionID: Args.string({\n\t\tname: 'collectionID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of collection',\n\t}),\n};\n\nmodule.exports = CollectionsRemoveCommand;\n"
  },
  {
    "path": "src/commands/comments/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass CommentsCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(CommentsCreateCommand);\n\t\tlet comment;\n\n\t\tif (flags.message) {\n\t\t\tcomment = await this.client.comments.create(\n\t\t\t\targs.fileID,\n\t\t\t\tflags.message\n\t\t\t);\n\t\t} else if (flags['tagged-message']) {\n\t\t\tcomment = await this.client.comments.createTaggedComment(\n\t\t\t\targs.fileID,\n\t\t\t\tflags['tagged-message']\n\t\t\t);\n\t\t}\n\t\tawait this.output(comment);\n\t}\n}\n\nCommentsCreateCommand.description = 'Create a comment on a file';\nCommentsCreateCommand.examples = [\n\t'box comments:create 11111 --message \"Thanks for the update!\"',\n];\nCommentsCreateCommand._endpoint = 'post_comments';\n\nCommentsCreateCommand.flags = {\n\t...BoxCommand.flags,\n\tmessage: Flags.string({\n\t\tdescription: 'Message of comment',\n\t\texclusive: ['tagged-message'],\n\t}),\n\t'tagged-message': Flags.string({\n\t\tdescription:\n\t\t\t'The text of the comment, including @[userid:Username] somewhere in the message to mention the user',\n\t\texclusive: ['message'],\n\t}),\n};\n\nCommentsCreateCommand.args = {\n\tfileID: Args.string({\n\t\tname: 'fileID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of file on which to comment',\n\t}),\n};\n\nmodule.exports = CommentsCreateCommand;\n"
  },
  {
    "path": "src/commands/comments/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass CommentsDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(CommentsDeleteCommand);\n\n\t\tawait this.client.comments.delete(args.id);\n\t\tthis.info(`Successfully deleted comment ${args.id}`);\n\t}\n}\n\nCommentsDeleteCommand.description = 'Delete a comment';\nCommentsDeleteCommand.examples = ['box comments:delete 12345'];\nCommentsDeleteCommand._endpoint = 'delete_comments_id';\n\nCommentsDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nCommentsDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the comment to delete',\n\t}),\n};\n\nmodule.exports = CommentsDeleteCommand;\n"
  },
  {
    "path": "src/commands/comments/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass CommentsGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(CommentsGetCommand);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet comment = await this.client.comments.get(args.id, options);\n\t\tawait this.output(comment);\n\t}\n}\n\nCommentsGetCommand.description = 'Get information about a comment';\nCommentsGetCommand.examples = ['box comments:get 12345'];\nCommentsGetCommand._endpoint = 'get_comments_id';\n\nCommentsGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nCommentsGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the comment to get',\n\t}),\n};\n\nmodule.exports = CommentsGetCommand;\n"
  },
  {
    "path": "src/commands/comments/reply.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass CommentsReplyCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(CommentsReplyCommand);\n\t\tlet parameters = {\n\t\t\tbody: {\n\t\t\t\titem: {\n\t\t\t\t\ttype: 'comment',\n\t\t\t\t\tid: args.id,\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\n\t\tif (flags.message) {\n\t\t\tparameters.body.message = flags.message;\n\t\t} else if (flags['tagged-message']) {\n\t\t\tparameters.body.tagged_message = flags['tagged-message'];\n\t\t}\n\n\t\t// @TODO (2018-07-28): Should implement this using the Node SDK\n\t\tlet comment = await this.client.wrapWithDefaultHandler(\n\t\t\tthis.client.post\n\t\t)('/comments', parameters);\n\t\tawait this.output(comment);\n\t}\n}\n\nCommentsReplyCommand.description = 'Reply to a comment';\nCommentsReplyCommand.examples = [\n\t'box comments:reply 12345 --message \"No problem!\"',\n];\n// TODO: Determine if this is the correct variant ID\n// CommentsReplyCommand._endpoint = 'post_comments reply';\n\nCommentsReplyCommand.flags = {\n\t...BoxCommand.flags,\n\tmessage: Flags.string({\n\t\tdescription: 'Message of comment',\n\t\texclusive: ['tagged-message'],\n\t}),\n\t'tagged-message': Flags.string({\n\t\tdescription:\n\t\t\t'The text of the comment, including @[userid:Username] somewhere in the message to mention the user',\n\t\texclusive: ['message'],\n\t}),\n};\n\nCommentsReplyCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the comment to reply to',\n\t}),\n};\n\nmodule.exports = CommentsReplyCommand;\n"
  },
  {
    "path": "src/commands/comments/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass CommentsUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(CommentsUpdateCommand);\n\t\tlet updates = {};\n\n\t\tif (flags.message) {\n\t\t\tupdates.message = flags.message;\n\t\t}\n\t\tif (flags['tagged-message']) {\n\t\t\tupdates.tagged_message = flags['tagged-message'];\n\t\t}\n\n\t\tlet comment = await this.client.comments.update(args.id, updates);\n\t\tawait this.output(comment);\n\t}\n}\n\nCommentsUpdateCommand.description = 'Update a comment';\nCommentsUpdateCommand.examples = [\n\t'box comments:update 12345 --message \"Thank you for the update!\"',\n];\nCommentsUpdateCommand._endpoint = 'put_comments_id';\n\nCommentsUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\tmessage: Flags.string({\n\t\tdescription: 'The text of the comment',\n\t\texclusive: ['tagged-message'],\n\t}),\n\t'tagged-message': Flags.string({\n\t\tdescription: 'The tagged text of the comment',\n\t\texclusive: ['message'],\n\t}),\n};\n\nCommentsUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the comment to update',\n\t}),\n};\n\nmodule.exports = CommentsUpdateCommand;\n"
  },
  {
    "path": "src/commands/configure/environments/add.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst fs = require('node:fs');\nconst BoxCLIError = require('../../../cli-error');\nconst chalk = require('chalk');\nconst utilities = require('../../../util');\n\nclass EnvironmentsAddCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(EnvironmentsAddCommand);\n\t\tlet environmentsObject = await this.getEnvironments();\n\t\tlet environmentName = flags.name;\n\t\tlet configFilePath = utilities.parsePath(args.path);\n\t\tlet configObject;\n\t\ttry {\n\t\t\tconfigObject = JSON.parse(fs.readFileSync(configFilePath));\n\t\t} catch (error) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t`Could not read environment config file ${args.path}`,\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\n\t\tconst isCCG = flags['ccg-auth'];\n\n\t\tutilities.validateConfigObject(configObject, isCCG);\n\n\t\tlet newEnvironment = {\n\t\t\tclientId: configObject.boxAppSettings.clientID,\n\t\t\tenterpriseId: configObject.enterpriseID,\n\t\t\tboxConfigFilePath: configFilePath,\n\t\t\thasInLinePrivateKey: true,\n\t\t\tprivateKeyPath: null,\n\t\t\tname: environmentName,\n\t\t\tdefaultAsUserId: null,\n\t\t\tuseDefaultAsUser: false,\n\t\t\t// @NOTE: These are legacy properties no longer in use\n\t\t\t// adminAsUserId: null,\n\t\t\t// tempAsUserId: null,\n\t\t\t// useTempAsUser: false,\n\t\t\t// userSessionExpiration: null,\n\t\t\t// userSessionEnabled: false,\n\t\t\tcacheTokens: true,\n\t\t};\n\n\t\tif (Object.hasOwn(environmentsObject.environments, environmentName)) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'There already is an environment with this name'\n\t\t\t);\n\t\t}\n\t\tif (!configObject.boxAppSettings.clientID) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Your configuration file is missing the client ID'\n\t\t\t);\n\t\t}\n\t\tif (!configObject.boxAppSettings.clientSecret) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Your configuration file is missing the client secret'\n\t\t\t);\n\t\t}\n\t\tif (!isCCG) {\n\t\t\tif (!configObject.boxAppSettings.appAuth.publicKeyID) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t'Your configuration file is missing the public key ID'\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (\n\t\t\t\t!configObject.boxAppSettings.appAuth.privateKey &&\n\t\t\t\t!flags['private-key-path']\n\t\t\t) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t'Your environment does not have a private key'\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!configObject.boxAppSettings.appAuth.passphrase) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t'Your environment does not have a passphrase'\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (!configObject.enterpriseID) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Your environment does not have an enterprise ID'\n\t\t\t);\n\t\t}\n\n\t\tif (flags['private-key-path']) {\n\t\t\tif (\n\t\t\t\t!fs.existsSync(flags['private-key-path']) ||\n\t\t\t\tfs.statSync(flags['private-key-path']).isDirectory()\n\t\t\t) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t`The private key path ${flags['private-key-path']} does not point to a file`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tnewEnvironment.privateKeyPath = flags['private-key-path'];\n\t\t\tnewEnvironment.hasInLinePrivateKey = false;\n\t\t}\n\t\tif (flags['set-as-current']) {\n\t\t\tenvironmentsObject.default = environmentName;\n\t\t}\n\n\t\t// If no default environment is defined, this newly added environment will be set as the default\n\t\tif (!environmentsObject.default) {\n\t\t\tenvironmentsObject.default = environmentName;\n\t\t}\n\n\t\tif (isCCG) {\n\t\t\tnewEnvironment.clientSecret =\n\t\t\t\tconfigObject.boxAppSettings.clientSecret;\n\t\t\tnewEnvironment.ccgUser = flags['ccg-user'];\n\t\t\tnewEnvironment.authMethod = 'ccg';\n\t\t}\n\n\t\tenvironmentsObject.environments[environmentName] = newEnvironment;\n\t\tawait this.updateEnvironments(environmentsObject);\n\t\tthis.info(\n\t\t\tchalk`{green Successfully added CLI environment \"${flags.name}\"}`\n\t\t);\n\t}\n}\n\n// @NOTE: This command MUST skip client setup, since it is used to add the first environment\nEnvironmentsAddCommand.noClient = true;\n\nEnvironmentsAddCommand.description =\n\t'Add a new Box environment from a Box app config file (JWT or CCG).\\n' +\n\t'Open your application in Box Developer Console to get/create config data:\\n' +\n\t'https://cloud.app.box.com/developers/console\\n' +\n\t'\\n' +\n\t'For OAuth (an alternative to server-side auth), add environment with: box login.\\n' +\n\t'Quick start: box login -d (logs the user in via the Box Official CLI App).';\nEnvironmentsAddCommand.examples = [\n\t'box configure:environments:add ~/Downloads/my_app_config.json',\n\t'box configure:environments:add ./config.json --name production --set-as-current',\n\t'box configure:environments:add ./config.json --ccg-auth --name ci-bot',\n];\n\nEnvironmentsAddCommand.flags = {\n\t...BoxCommand.minFlags,\n\t'private-key-path': Flags.string({\n\t\tdescription: 'Provide a path to application private key',\n\t\tparse: utilities.parsePath,\n\t}),\n\t'set-as-current': Flags.boolean({\n\t\tdescription: 'Set this new environment as your current environment',\n\t}),\n\tname: Flags.string({\n\t\tchar: 'n',\n\t\tdescription: 'Set a name for the environment',\n\t\tdefault: 'default',\n\t}),\n\t'ccg-auth': Flags.boolean({\n\t\tdescription:\n\t\t\t'Add a CCG environment that will use a service account.\\n' +\n\t\t\t'Open your application in Box Developer Console and create this config JSON yourself.\\n' +\n\t\t\t'Required fields: boxAppSettings.clientID, boxAppSettings.clientSecret, enterpriseID.',\n\t}),\n\t'ccg-user': Flags.string({\n\t\tdescription:\n\t\t\t'Provide an ID for a user for CCG. Use it to obtain user token. ' +\n\t\t\t'In order to enable generating user token you have to go to your application ' +\n\t\t\t'configuration that can be found here https://app.box.com/developers/console.\\n' +\n\t\t\t'In`Configuration` tab, in section `Advanced Features` select `Generate user access tokens`. \\n' +\n\t\t\t'Do not forget to re-authorize application if it was already authorized.',\n\t\tdependsOn: ['ccg-auth'],\n\t}),\n};\n\nEnvironmentsAddCommand.args = {\n\tpath: Args.string({\n\t\tname: 'path',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription:\n\t\t\t'Path to the Box app configuration JSON file.\\n' +\n\t\t\t'JWT: download this file from your application in Developer Console:\\n' +\n\t\t\t'https://cloud.app.box.com/developers/console\\n' +\n\t\t\t'CCG: create this JSON file yourself using values from your application\\n' +\n\t\t\t'in Developer Console (Client ID and Client Secret from Configuration tab,\\n' +\n\t\t\t'Enterprise ID from General Settings tab).',\n\t}),\n};\n\nmodule.exports = EnvironmentsAddCommand;\n"
  },
  {
    "path": "src/commands/configure/environments/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\nconst BoxCLIError = require('../../../cli-error');\nconst inquirer = require('../../../inquirer');\n\nclass EnvironmentsDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(EnvironmentsDeleteCommand);\n\t\tlet environmentsObject = await this.getEnvironments();\n\t\tlet name = args.name;\n\n\t\tif (!name) {\n\t\t\tconst choices = Object.keys(environmentsObject.environments);\n\t\t\tif (choices.length === 0) {\n\t\t\t\tthrow new BoxCLIError('No environments to delete');\n\t\t\t}\n\t\t\tlet answers = await inquirer.prompt([\n\t\t\t\t{\n\t\t\t\t\ttype: 'list',\n\t\t\t\t\tname: 'environment',\n\t\t\t\t\tmessage: 'Which environment?',\n\t\t\t\t\tchoices: Object.keys(environmentsObject.environments),\n\t\t\t\t},\n\t\t\t]);\n\t\t\tname = answers.environment;\n\t\t}\n\n\t\tif (Object.hasOwn(environmentsObject.environments, name)) {\n\t\t\tdelete environmentsObject.environments[name];\n\t\t\tif (environmentsObject.default === name) {\n\t\t\t\tenvironmentsObject.default = '';\n\t\t\t}\n\t\t\tawait this.updateEnvironments(environmentsObject);\n\t\t\tthis.info(`The ${name} environment was deleted`);\n\t\t} else {\n\t\t\tthis.error(`The ${name} environment does not exist`);\n\t\t}\n\t}\n}\n\n// @NOTE: This command does not require a client to be set up\nEnvironmentsDeleteCommand.noClient = true;\n\nEnvironmentsDeleteCommand.description = 'Delete a Box environment';\n\nEnvironmentsDeleteCommand.flags = {\n\t...BoxCommand.minFlags,\n};\n\nEnvironmentsDeleteCommand.args = {\n\tname: Args.string({\n\t\tname: 'name',\n\t\trequired: false,\n\t\thidden: false,\n\t\tdescription: 'Name of the environment',\n\t}),\n};\n\nmodule.exports = EnvironmentsDeleteCommand;\n"
  },
  {
    "path": "src/commands/configure/environments/get.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags } = require('@oclif/core');\nconst _ = require('lodash');\nconst utilities = require('../../../util');\n\nclass EnvironmentsGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(EnvironmentsGetCommand);\n\t\tlet environmentsObject = await this.getEnvironments();\n\t\tlet environment;\n\n\t\tif (flags.current) {\n\t\t\tlet currentEnvironment = environmentsObject.default;\n\t\t\tenvironment = environmentsObject.environments[currentEnvironment];\n\t\t} else if (flags.name) {\n\t\t\tenvironment = environmentsObject.environments[flags.name];\n\t\t} else {\n\t\t\tenvironment = environmentsObject.environments;\n\t\t}\n\n\t\tif (_.isEmpty(environment)) {\n\t\t\tthis.error('No environment(s) exists');\n\t\t} else {\n\t\t\tawait this.output(utilities.maskObjectValuesByKey(environment));\n\t\t}\n\t}\n}\n\n// @NOTE: This command does not require a client to be set up\nEnvironmentsGetCommand.noClient = true;\nEnvironmentsGetCommand.aliases = ['configure:environments:list'];\n\nEnvironmentsGetCommand.description =\n\t'Get a Box environment or list all configured Box environments.\\nclientSecret values are masked in CLI output. To view full secrets, access secure storage directly (for example, macOS Keychain, Windows Credential Manager, or a supported Linux equivalent).';\n\nEnvironmentsGetCommand.flags = {\n\t...BoxCommand.minFlags,\n\tcurrent: Flags.boolean({\n\t\tchar: 'c',\n\t\tdescription: 'Get the current default Box environment',\n\t\texclusive: ['name'],\n\t}),\n\tname: Flags.string({\n\t\tchar: 'n',\n\t\tdescription: 'Get a Box environment with this name',\n\t\texclusive: ['current'],\n\t}),\n};\n\nmodule.exports = EnvironmentsGetCommand;\n"
  },
  {
    "path": "src/commands/configure/environments/set-current.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\nconst inquirer = require('../../../inquirer');\n\nclass EnvironmentsSetCurrentCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(EnvironmentsSetCurrentCommand);\n\t\tlet environmentsObject = await this.getEnvironments();\n\t\tlet name = args.id;\n\n\t\tif (!name) {\n\t\t\tlet answers = await inquirer.prompt([\n\t\t\t\t{\n\t\t\t\t\ttype: 'list',\n\t\t\t\t\tname: 'environment',\n\t\t\t\t\tmessage: 'Which environment?',\n\t\t\t\t\tchoices: Object.keys(environmentsObject.environments),\n\t\t\t\t},\n\t\t\t]);\n\t\t\tname = answers.environment;\n\t\t}\n\n\t\tif (Object.hasOwn(environmentsObject.environments, name)) {\n\t\t\tenvironmentsObject.default = name;\n\t\t\tawait this.updateEnvironments(environmentsObject);\n\t\t\tthis.info(`The ${name} environment has been set as the default`);\n\t\t} else {\n\t\t\tthis.error(`The ${name} environment does not exist`);\n\t\t}\n\t}\n}\n\n// @NOTE: This command does not require a client to be set up\nEnvironmentsSetCurrentCommand.noClient = true;\n\nEnvironmentsSetCurrentCommand.aliases = ['configure:environments:select'];\nEnvironmentsSetCurrentCommand.description =\n\t'Set your current Box environment to use';\n\nEnvironmentsSetCurrentCommand.flags = {\n\t...BoxCommand.minFlags,\n};\n\nEnvironmentsSetCurrentCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: false,\n\t\thidden: false,\n\t\tdescription: 'Name of the environment',\n\t}),\n};\n\nmodule.exports = EnvironmentsSetCurrentCommand;\n"
  },
  {
    "path": "src/commands/configure/environments/switch-user.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst chalk = require('chalk');\n\nclass EnvironmentsSwitchUserCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(EnvironmentsSwitchUserCommand);\n\n\t\tlet environmentsObject = await this.getEnvironments();\n\t\tlet environment =\n\t\t\tenvironmentsObject.environments[environmentsObject.default];\n\n\t\tif (flags.default && !args.userID) {\n\t\t\tenvironment.useDefaultAsUser = false;\n\t\t} else if (args.userID && !flags.default) {\n\t\t\tenvironment.useDefaultAsUser = true;\n\t\t\tenvironment.defaultAsUserId = args.userID;\n\t\t} else {\n\t\t\tthrow new Error(\n\t\t\t\t'Either a userID argument or --default flag must be passed, but not both'\n\t\t\t);\n\t\t}\n\n\t\tawait this.updateEnvironments(environmentsObject);\n\t\tthis.info(chalk`{green User set to ${args.userID || 'default'}}`);\n\t}\n}\n\n// @NOTE: This command does not require a client to be set up\nEnvironmentsSwitchUserCommand.noClient = true;\n\nEnvironmentsSwitchUserCommand.description =\n\t'Switch the default Box user to run commands as';\n\nEnvironmentsSwitchUserCommand.flags = {\n\t...BoxCommand.minFlags,\n};\n\nEnvironmentsSwitchUserCommand.args = {\n\tuserID: Args.string({\n\t\tname: 'userID',\n\t\thidden: false,\n\t\trequired: false,\n\t\tdescription: 'The user ID to switch to',\n\t}),\n};\n\nEnvironmentsSwitchUserCommand.flags = {\n\t...BoxCommand.flags,\n\tdefault: Flags.boolean({\n\t\tdescription: 'Switch to the default user, i.e. the Service Account',\n\t}),\n};\n\nmodule.exports = EnvironmentsSwitchUserCommand;\n"
  },
  {
    "path": "src/commands/configure/environments/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst fs = require('node:fs');\nconst BoxCLIError = require('../../../cli-error');\nconst utilities = require('../../../util');\n\nclass EnvironmentsUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(EnvironmentsUpdateCommand);\n\t\tlet environmentsObject = await this.getEnvironments();\n\t\tlet environment =\n\t\t\tenvironmentsObject.environments[\n\t\t\t\targs.name || environmentsObject.default\n\t\t\t];\n\n\t\tif (!environment) {\n\t\t\tthis.error('There is no environment with this name');\n\t\t\treturn;\n\t\t}\n\n\t\tif (flags['config-file-path']) {\n\t\t\tlet configObject;\n\t\t\ttry {\n\t\t\t\tconfigObject = JSON.parse(\n\t\t\t\t\tfs.readFileSync(flags['config-file-path'], 'utf8')\n\t\t\t\t);\n\t\t\t} catch (error) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t`Could not read environment config file ${flags['config-file-path']}`,\n\t\t\t\t\terror\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tutilities.validateConfigObject(configObject);\n\n\t\t\tif (\n\t\t\t\t!configObject.boxAppSettings.appAuth.privateKey &&\n\t\t\t\t!flags['private-key-path'] &&\n\t\t\t\tenvironment.hasInLinePrivateKey\n\t\t\t) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t'Environment must specify private key in config file or via --private-key-path'\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (configObject.boxAppSettings.appAuth.privateKey) {\n\t\t\t\tenvironment.privateKeyPath = '';\n\t\t\t\tenvironment.hasInLinePrivateKey = true;\n\t\t\t}\n\t\t\tenvironment.boxConfigFilePath = flags['config-file-path'];\n\t\t}\n\t\tif (flags.name) {\n\t\t\tenvironment.name = flags.name;\n\t\t}\n\t\tif (flags['private-key-path']) {\n\t\t\tenvironment.privateKeyPath = flags['private-key-path'];\n\t\t\tenvironment.hasInLinePrivateKey = false;\n\t\t}\n\t\tif (flags['user-id']) {\n\t\t\tenvironment.defaultAsUserId = flags['user-id'];\n\t\t\tenvironment.useDefaultAsUser = true;\n\t\t}\n\n\t\tif (Object.hasOwn(flags, 'cache-tokens')) {\n\t\t\tenvironment.cacheTokens = flags['cache-tokens'];\n\t\t}\n\n\t\tawait this.updateEnvironments(environmentsObject);\n\t\tawait this.output(utilities.maskObjectValuesByKey(environment));\n\t}\n}\n\n// @NOTE: This command does not require a client to be set up\nEnvironmentsUpdateCommand.noClient = true;\n\nEnvironmentsUpdateCommand.description = 'Update a Box environment';\n\nEnvironmentsUpdateCommand.flags = {\n\t...BoxCommand.minFlags,\n\t'config-file-path': Flags.string({\n\t\tdescription: 'Provide a file path to configuration file',\n\t\tparse: utilities.parsePath,\n\t}),\n\tname: Flags.string({ description: 'New name of the environment' }),\n\t'private-key-path': Flags.string({\n\t\tdescription: 'Provide a file path to application private key',\n\t\tparse: utilities.parsePath,\n\t}),\n\t'user-id': Flags.string({\n\t\tdescription:\n\t\t\t'Store a default user ID to use with the session commands. A default user ID can be stored for each Box environment',\n\t}),\n\t'cache-tokens': Flags.boolean({\n\t\tdescription:\n\t\t\t'Enable token caching, which significantly improves performance. Run with --no-cache-tokens and then --cache-tokens if your application config updates are not reflected in your requests.',\n\t\tallowNo: true,\n\t}),\n};\n\nEnvironmentsUpdateCommand.args = {\n\tname: Args.string({\n\t\tname: 'name',\n\t\trequired: false,\n\t\thidden: false,\n\t\tdescription: 'The name of the environment',\n\t}),\n};\n\nmodule.exports = EnvironmentsUpdateCommand;\n"
  },
  {
    "path": "src/commands/configure/settings.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\nconst fs = require('node:fs');\nconst { mkdirp } = require('mkdirp');\nconst BoxCLIError = require('../../cli-error');\nconst utilities = require('../../util');\n\nclass ConfigureSettingsCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(ConfigureSettingsCommand);\n\t\tlet settings = this.settings;\n\n\t\tif (flags['downloads-folder-path']) {\n\t\t\tlet downloadsPath = flags['downloads-folder-path'];\n\t\t\tif (!fs.existsSync(downloadsPath)) {\n\t\t\t\tlet shouldCreate = await this.confirm(\n\t\t\t\t\t`Folder ${downloadsPath} does not exist; create it?`\n\t\t\t\t);\n\n\t\t\t\tif (!shouldCreate) {\n\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t'Could not update settings due to incorrect folder path'\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tawait mkdirp(downloadsPath);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t'Could not create downloads directory',\n\t\t\t\t\t\terror\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else if (!fs.statSync(downloadsPath).isDirectory()) {\n\t\t\t\tthrow new BoxCLIError(`${downloadsPath} is not a directory!`);\n\t\t\t}\n\n\t\t\tsettings.boxDownloadsFolderPath = downloadsPath;\n\t\t}\n\t\tif (flags['file-format']) {\n\t\t\tsettings.boxReportsFileFormat = flags['file-format'];\n\t\t}\n\t\tif (flags['reports-folder-path']) {\n\t\t\tlet reportsPath = flags['reports-folder-path'];\n\t\t\tif (!fs.existsSync(reportsPath)) {\n\t\t\t\tlet shouldCreate = await this.confirm(\n\t\t\t\t\t`Folder ${reportsPath} does not exist; create it?`\n\t\t\t\t);\n\n\t\t\t\tif (!shouldCreate) {\n\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t'Could not update settings due to incorrect folder path'\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tawait mkdirp(reportsPath);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t'Could not create downloads directory',\n\t\t\t\t\t\terror\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else if (!fs.statSync(reportsPath).isDirectory()) {\n\t\t\t\tthrow new BoxCLIError(`${reportsPath} is not a directory!`);\n\t\t\t}\n\t\t\tsettings.boxReportsFolderPath = reportsPath;\n\t\t}\n\t\tif (Object.hasOwn(flags, 'output-json')) {\n\t\t\tsettings.outputJson = flags['output-json'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'enable-proxy')) {\n\t\t\tsettings.enableProxy = flags['enable-proxy'];\n\t\t}\n\t\tif (flags['proxy-url']) {\n\t\t\tsettings.proxy.url = flags['proxy-url'];\n\t\t}\n\t\tif (flags['proxy-username']) {\n\t\t\tsettings.proxy.username = flags['proxy-username'];\n\t\t}\n\t\tif (flags['proxy-password']) {\n\t\t\tsettings.proxy.password = flags['proxy-password'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'enable-analytics-client')) {\n\t\t\tsettings.enableAnalyticsClient = flags['enable-analytics-client'];\n\t\t}\n\t\tif (flags['analytics-client-name']) {\n\t\t\tsettings.analyticsClient.name = flags['analytics-client-name'];\n\t\t}\n\n\t\tthis.updateSettings(settings);\n\t\tawait this.output(settings);\n\t}\n}\n\n// @NOTE: This command does not require a client to be set up\nConfigureSettingsCommand.noClient = true;\n\nConfigureSettingsCommand.description =\n\t'View and update CLI configuration settings';\n\nConfigureSettingsCommand.flags = {\n\t...BoxCommand.minFlags,\n\tjson: Flags.boolean({\n\t\tdescription: 'Output CLI configuration settings in JSON format',\n\t}),\n\t'enable-proxy': Flags.boolean({\n\t\tdescription: 'Enable or disable proxy',\n\t\tallowNo: true,\n\t}),\n\t'proxy-url': Flags.string({\n\t\tdescription:\n\t\t\t'Set proxy url, which should contain the protocol, url, and port (i.e. http://sample.proxyurl.com:80)',\n\t}),\n\t'proxy-username': Flags.string({\n\t\tdescription: 'Set username for proxy',\n\t\tdependsOn: ['proxy-password'],\n\t}),\n\t'proxy-password': Flags.string({\n\t\tdescription: 'Set password for proxy',\n\t\tdependsOn: ['proxy-username'],\n\t}),\n\t'downloads-folder-path': Flags.string({\n\t\tdescription: 'Set folder path for the downloads folder',\n\t\tparse: utilities.parsePath,\n\t}),\n\t'file-format': Flags.string({\n\t\tdescription: 'Set the file format for generated reports',\n\t\toptions: ['csv', 'json', 'txt'],\n\t}),\n\t'output-json': Flags.boolean({\n\t\tdescription: 'Default to JSON output for all commands',\n\t\tallowNo: true,\n\t}),\n\t'reports-folder-path': Flags.string({\n\t\tdescription: 'Set folder path for the reports folder',\n\t\tparse: utilities.parsePath,\n\t}),\n\t'enable-analytics-client': Flags.boolean({\n\t\tdescription: 'Enable or disable custom analytics client',\n\t\tallowNo: true,\n\t}),\n\t'analytics-client-name': Flags.string({\n\t\tdescription: 'Set custom analytics client header value',\n\t}),\n};\n\nmodule.exports = ConfigureSettingsCommand;\n"
  },
  {
    "path": "src/commands/device-pins/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass DevicePinsDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(DevicePinsDeleteCommand);\n\n\t\tawait this.client.devicePins.delete(args.id);\n\t\tthis.info(`Deleted device pin ${args.id}`);\n\t}\n}\n\nDevicePinsDeleteCommand.description = 'Delete individual device pin';\nDevicePinsDeleteCommand.examples = ['box device-pins:delete 12345'];\nDevicePinsDeleteCommand._endpoint = 'delete_device_pinners_id';\n\nDevicePinsDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nDevicePinsDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the device pin to delete',\n\t}),\n};\n\nmodule.exports = DevicePinsDeleteCommand;\n"
  },
  {
    "path": "src/commands/device-pins/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass DevicePinsGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(DevicePinsGetCommand);\n\n\t\tlet pin = await this.client.devicePins.get(args.id);\n\t\tawait this.output(pin);\n\t}\n}\n\nDevicePinsGetCommand.description =\n\t'Get information about an individual device pin';\nDevicePinsGetCommand.examples = ['box device-pins:get 12345'];\nDevicePinsGetCommand._endpoint = 'get_device_pinners_id';\n\nDevicePinsGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nDevicePinsGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the device pin to get',\n\t}),\n};\n\nmodule.exports = DevicePinsGetCommand;\n"
  },
  {
    "path": "src/commands/device-pins/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass DevicePinsListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(DevicePinsListCommand);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.direction) {\n\t\t\toptions.direction = flags.direction;\n\t\t}\n\n\t\tlet pins = await this.client.devicePins.getAll(options);\n\t\tawait this.output(pins);\n\t}\n}\n\nDevicePinsListCommand.description =\n\t'List all the device pins for your enterprise';\nDevicePinsListCommand.examples = ['box device-pins'];\nDevicePinsListCommand._endpoint = 'get_enterprises_id_device_pinners';\n\nDevicePinsListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n\tdirection: Flags.string({\n\t\tdescription: 'Set sorting (by id) direction. Default is ASC',\n\t\toptions: ['ASC', 'DESC'],\n\t}),\n};\n\nmodule.exports = DevicePinsListCommand;\n"
  },
  {
    "path": "src/commands/events/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\nconst date = require('date-fns');\n\nconst DEFAULT_START_TIME = '-5d';\nconst DEFAULT_END_TIME = 'now';\n\nconst eventReplacements = {\n\tADMIN_INVITE_ACCEPT: 'MASTER_INVITE_ACCEPT',\n\tADMIN_INVITE_REJECT: 'MASTER_INVITE_REJECT',\n};\n\nclass EventsGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(EventsGetCommand);\n\t\tlet options = {};\n\n\t\tif (flags.enterprise) {\n\t\t\toptions.stream_type = flags['stream-type'] || 'admin_logs';\n\t\t}\n\t\tif (flags.limit) {\n\t\t\toptions.limit = flags.limit;\n\t\t}\n\t\tif (flags['event-types']) {\n\t\t\tconst joinedEvents = flags['event-types'];\n\t\t\tconst events = joinedEvents.split(',');\n\t\t\tconst mappedEvents = events.map((event) => {\n\t\t\t\tconst replacement = eventReplacements[event];\n\t\t\t\treturn replacement || event;\n\t\t\t});\n\t\t\toptions.event_type = mappedEvents.join(',');\n\t\t}\n\n\t\tif (flags['stream-position']) {\n\t\t\toptions.stream_position = flags['stream-position'];\n\t\t} else if (options.stream_type === 'admin_logs') {\n\t\t\toptions.created_before =\n\t\t\t\tflags['created-before'] ||\n\t\t\t\tBoxCommand.normalizeDateString(DEFAULT_END_TIME);\n\n\t\t\tif (flags['created-before'] && !flags['created-after']) {\n\t\t\t\t// If the user specified an end time but no start time, recompute the default start time as\n\t\t\t\t// the specified end time minus five days\n\t\t\t\tlet endTime = date.addDays(\n\t\t\t\t\tdate.parse(options.created_before),\n\t\t\t\t\t-5\n\t\t\t\t);\n\t\t\t\toptions.created_after = endTime\n\t\t\t\t\t.toISOString()\n\t\t\t\t\t.replace(/\\.\\d{3}Z$/u, '+00:00');\n\t\t\t} else {\n\t\t\t\toptions.created_after =\n\t\t\t\t\tflags['created-after'] ||\n\t\t\t\t\tBoxCommand.normalizeDateString(DEFAULT_START_TIME);\n\t\t\t}\n\t\t}\n\n\t\tlet events = await this.client.events.get(options);\n\t\tconst isNotAdminTypeStream =\n\t\t\toptions.stream_type !== 'admin_logs' &&\n\t\t\toptions.stream_type !== 'admin_logs_streaming';\n\t\tif (options.stream_position || isNotAdminTypeStream) {\n\t\t\tawait this.output(events);\n\t\t} else {\n\t\t\tlet allEvents = [events.entries].flat(); // Copy the first page of events\n\n\t\t\t// @NOTE: The Events API doesn't return any of the usual indications that the end of paging has been\n\t\t\t// reached, but does appear to return a \"next stream position\" that's the same as the one passed in\n\t\t\twhile (options.stream_position !== events.next_stream_position) {\n\t\t\t\toptions.stream_position = events.next_stream_position;\n\n\t\t\t\tevents = await this.client.events.get(options);\n\n\t\t\t\tfor (const event of events.entries) allEvents.push(event);\n\t\t\t}\n\n\t\t\tawait this.output(allEvents);\n\t\t}\n\t}\n}\n\nEventsGetCommand.aliases = ['events:get'];\n\nEventsGetCommand.description = 'Get events';\nEventsGetCommand.examples = [\n\t'box events',\n\t'box events --enterprise --created-after 2019-01-01',\n];\nEventsGetCommand._endpoint = 'get_events';\n\nEventsGetCommand.flags = {\n\t...BoxCommand.flags,\n\tenterprise: Flags.boolean({\n\t\tchar: 'e',\n\t\tdescription:\n\t\t\t'Get all enterprise events form a given criteria.\\n' +\n\t\t\t'CLI will use the `next_stream_position` automatically to fetch all records.',\n\t}),\n\t'created-after': Flags.string({\n\t\tdescription:\n\t\t\t'Return enterprise events that occurred after a time. Use a timestamp or shorthand syntax 0t, like 5w for 5 weeks. If not used, defaults to 5 days before the end date',\n\t\texclusive: ['stream_position'],\n\t\tdependsOn: ['enterprise'],\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'created-before': Flags.string({\n\t\tdescription:\n\t\t\t'Return enterprise events that occurred before a time. Use a timestamp or shorthand syntax 0t, like 5w for 5 weeks. If not used, defaults to now',\n\t\texclusive: ['stream_position'],\n\t\tdependsOn: ['enterprise'],\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'event-types': Flags.string({\n\t\tdescription:\n\t\t\t'Return enterprise events filtered by event types. Format using a comma delimited list: NEW_USER,DELETE_USER,EDIT_USER',\n\t}),\n\t'stream-position': Flags.string({\n\t\tdescription:\n\t\t\t'The location in the event stream from which you want to start receiving events',\n\t\texclusive: ['created-before', 'created-after'],\n\t}),\n\tlimit: Flags.integer({\n\t\tdescription:\n\t\t\t'The maximum number of items to return.\\n' +\n\t\t\t'When using it with `enterprise` events, it determines the number of items to return per API call. ' +\n\t\t\t'The CLI will automatically use the `next_stream_position` to fetch all records.',\n\t}),\n\t'stream-type': Flags.string({\n\t\tdescription:\n\t\t\t'Stream type admin_logs or admin_logs_streaming.\\n' +\n\t\t\t'Unless specified `admin_logs` stream type is used.\\n\\n' +\n\t\t\t'The emphasis for `admin_logs` stream is on completeness over latency, which means that Box will ' +\n\t\t\t'deliver admin events in chronological order and without duplicates, but with higher latency. ' +\n\t\t\t'You can specify start and end time/dates.\\n\\n' +\n\t\t\t'The emphasis for `admin_logs_streaming` feed is on low latency rather than chronological accuracy, ' +\n\t\t\t'which means that Box may return events more than once and out of chronological order. Events are ' +\n\t\t\t'returned via the API around 12 seconds after they are processed by Box (the 12 seconds buffer ' +\n\t\t\t'ensures that new events are not written after your cursor position). Only two weeks of events are ' +\n\t\t\t'available via this feed, and you cannot set start and end time/dates.',\n\t\tdependsOn: ['enterprise'],\n\t\toptions: ['admin_logs', 'admin_logs_streaming'],\n\t}),\n};\n\nmodule.exports = EventsGetCommand;\n"
  },
  {
    "path": "src/commands/events/poll.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\nconst pEvent = require('p-event');\n\nclass EventsPollCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(EventsPollCommand);\n\t\tlet stream;\n\t\tlet options = {};\n\n\t\tif (flags['event-types']) {\n\t\t\toptions.event_type = flags['event-types'];\n\t\t}\n\t\tif (flags['start-date']) {\n\t\t\toptions.startDate = flags['start-date'];\n\t\t}\n\t\tif (flags['end-date']) {\n\t\t\toptions.endDate = flags['end-date'];\n\t\t}\n\t\tif (flags['polling-interval']) {\n\t\t\tif (flags.enterprise) {\n\t\t\t\toptions.pollingInterval = flags['polling-interval'];\n\t\t\t} else {\n\t\t\t\toptions.fetchInterval = flags['polling-interval'] * 1000;\n\t\t\t}\n\t\t}\n\n\t\tawait this.output('Polling started...');\n\t\tstream = await (flags.enterprise\n\t\t\t? this.client.events.getEnterpriseEventStream(options)\n\t\t\t: this.client.events.getEventStream(options));\n\n\t\tlet events = pEvent.iterator(stream, 'data');\n\n\t\tfor await (let event of events) {\n\t\t\tawait this.output(event);\n\t\t\tawait this.output('**************************');\n\t\t}\n\t}\n}\n\nEventsPollCommand.description = 'Poll the event stream';\n\nEventsPollCommand.flags = {\n\t...BoxCommand.flags,\n\tenterprise: Flags.boolean({\n\t\tchar: 'e',\n\t\tdescription: 'Get enterprise events',\n\t}),\n\t'event-types': Flags.string({\n\t\tdescription:\n\t\t\t'Return enterprise events filtered by event types. Format using a comma delimited list: NEW_USER,DELETE_USER,EDIT_USER',\n\t}),\n\t'start-date': Flags.string({\n\t\tdescription:\n\t\t\t'Return enterprise events that occured after this time. Use a timestamp or shorthand syntax 00t, like 05w for 5 weeks. If not used, defaults to now',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'end-date': Flags.string({\n\t\tdescription:\n\t\t\t'Return enterprise events that occured before this time. Use a timestamp or shorthand syntax 00t, like 05w for 5 weeks.',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'polling-interval': Flags.string({\n\t\tdescription:\n\t\t\t'Number of seconds to wait before polling for new events. Default is 60 seconds.',\n\t\tparse: (input) => Number.parseInt(input, 10),\n\t}),\n};\n\nmodule.exports = EventsPollCommand;\n"
  },
  {
    "path": "src/commands/file-requests/copy.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass FileRequestsCopyCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FileRequestsCopyCommand);\n\t\tlet options = { folder: { type: 'folder' } };\n\n\t\tif (args.folderID) {\n\t\t\toptions.folder.id = args.folderID;\n\t\t}\n\n\t\tif (flags.title) {\n\t\t\toptions.title = flags.title;\n\t\t}\n\n\t\tif (flags.description) {\n\t\t\toptions.description = flags.description;\n\t\t}\n\n\t\tif (flags['expires-at']) {\n\t\t\toptions.expires_at = flags['expires-at'];\n\t\t}\n\n\t\tif (flags['description-required']) {\n\t\t\toptions.is_description_required = flags['description-required'];\n\t\t}\n\n\t\tif (flags['email-required']) {\n\t\t\toptions.is_email_required = flags['email-required'];\n\t\t}\n\n\t\tif (flags.status) {\n\t\t\toptions.status = flags.status;\n\t\t}\n\n\t\tlet fileRequest = await this.client.fileRequests.copy(args.id, options);\n\t\tawait this.output(fileRequest);\n\t}\n}\n\nFileRequestsCopyCommand.description =\n\t'Copies existing file request to new folder';\nFileRequestsCopyCommand.examples = ['box file-requests:copy 22222 44444'];\nFileRequestsCopyCommand._endpoint = 'post_file_requests_id_copy';\n\nFileRequestsCopyCommand.flags = {\n\t...BoxCommand.flags,\n\tdescription: Flags.string({\n\t\tdescription: 'New description of file request',\n\t\tparse: utilities.unescapeSlashes,\n\t}),\n\t'expires-at': Flags.string({\n\t\tdescription: 'New date when file request expires',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'description-required': Flags.boolean({\n\t\tdescription:\n\t\t\t'is file request submitter required to provide a description of the files they are submitting',\n\t\tallowNo: true,\n\t}),\n\t'email-required': Flags.boolean({\n\t\tdescription: 'New date when file request expires',\n\t\tallowNo: true,\n\t}),\n\tstatus: Flags.string({\n\t\tdescription: 'New status of file request',\n\t\toptions: ['active', 'inactive'],\n\t}),\n\ttitle: Flags.string({\n\t\tdescription: 'New title of file request',\n\t}),\n};\nFileRequestsCopyCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file request to copy',\n\t}),\n\tfolderID: Args.string({\n\t\tname: 'folderID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of folder to which file request will be copied',\n\t}),\n};\n\nmodule.exports = FileRequestsCopyCommand;\n"
  },
  {
    "path": "src/commands/file-requests/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass FileRequestsDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(FileRequestsDeleteCommand);\n\n\t\tawait this.client.fileRequests.delete(args.id);\n\t\tthis.info(`Deleted file request ${args.id}`);\n\t}\n}\n\nFileRequestsDeleteCommand.description = 'Delete individual file request';\nFileRequestsDeleteCommand.examples = ['box file-requests:delete 12345'];\nFileRequestsDeleteCommand._endpoint = 'delete_file_requests_id';\n\nFileRequestsDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nFileRequestsDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file request to delete',\n\t}),\n};\n\nmodule.exports = FileRequestsDeleteCommand;\n"
  },
  {
    "path": "src/commands/file-requests/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass FileRequestsGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(FileRequestsGetCommand);\n\n\t\tlet fileRequest = await this.client.fileRequests.getById(args.id);\n\t\tawait this.output(fileRequest);\n\t}\n}\n\nFileRequestsGetCommand.description = 'Get information about an file request';\nFileRequestsGetCommand.examples = ['box file-requests:get 12345'];\nFileRequestsGetCommand._endpoint = 'get_file_requests_id';\n\nFileRequestsGetCommand.flags = {\n\t...BoxCommand.flags,\n};\nFileRequestsGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file request to get',\n\t}),\n};\n\nmodule.exports = FileRequestsGetCommand;\n"
  },
  {
    "path": "src/commands/file-requests/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass FileRequestsUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FileRequestsUpdateCommand);\n\t\tlet updates = {};\n\t\tlet etag = '';\n\n\t\tif (flags.description) {\n\t\t\tupdates.description = flags.description;\n\t\t}\n\n\t\tif (flags['expires-at']) {\n\t\t\tupdates.expires_at = flags['expires-at'];\n\t\t}\n\n\t\tif (flags['description-required']) {\n\t\t\tupdates.is_description_required = flags['description-required'];\n\t\t}\n\n\t\tif (flags['email-required']) {\n\t\t\tupdates.is_email_required = flags['email-required'];\n\t\t}\n\n\t\tif (flags.status) {\n\t\t\tupdates.status = flags.status;\n\t\t}\n\n\t\tif (flags.title) {\n\t\t\tupdates.title = flags.title;\n\t\t}\n\n\t\tif (flags.etag) {\n\t\t\tetag = flags.etag;\n\t\t}\n\n\t\tlet fileRequest = await this.client.fileRequests.update(\n\t\t\targs.id,\n\t\t\tupdates,\n\t\t\tetag\n\t\t);\n\t\tawait this.output(fileRequest);\n\t}\n}\n\nFileRequestsUpdateCommand.description = 'Update a file request';\nFileRequestsUpdateCommand.examples = [\n\t'box file-requests:update 12345 --description \"New file request description!\"',\n];\nFileRequestsUpdateCommand._endpoint = 'put_file_requests_id';\n\nFileRequestsUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\tdescription: Flags.string({\n\t\tdescription: 'New description of file request',\n\t\tparse: utilities.unescapeSlashes,\n\t}),\n\t'expires-at': Flags.string({\n\t\tdescription: 'New date when file request expires',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'description-required': Flags.boolean({\n\t\tdescription:\n\t\t\t'is file request submitter required to provide a description of the files they are submitting',\n\t\tallowNo: true,\n\t}),\n\t'email-required': Flags.boolean({\n\t\tdescription: 'New date when file request expires',\n\t\tallowNo: true,\n\t}),\n\tstatus: Flags.string({\n\t\tdescription: 'New status of file request',\n\t\toptions: ['active', 'inactive'],\n\t}),\n\ttitle: Flags.string({\n\t\tdescription: 'New title of file request',\n\t}),\n\tetag: Flags.string({\n\t\tdescription:\n\t\t\t\"Pass in the item's last observed etag value into this header and the endpoint will fail with a 412 Precondition Failed if it has changed since.\",\n\t}),\n};\n\nFileRequestsUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file request to update',\n\t}),\n};\n\nmodule.exports = FileRequestsUpdateCommand;\n"
  },
  {
    "path": "src/commands/files/collaborations/add.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Args } = require('@oclif/core');\nconst CollaborationsCreateCommand = require('../../collaborations/create');\nconst CollaborationModule = require('../../../modules/collaboration');\n\nclass FilesCollaborationsAddCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args, flags } = await this.parse(FilesCollaborationsAddCommand);\n\n\t\t// Transform arguments for generic module\n\t\targs.itemType = 'file';\n\t\targs.itemID = args.id;\n\t\tdelete args.id;\n\n\t\tlet collabModule = new CollaborationModule(this.client);\n\t\tlet collaboration = await collabModule.createCollaboration(args, flags);\n\t\tawait this.output(collaboration);\n\t}\n}\n\nFilesCollaborationsAddCommand.description = 'Create a collaboration for a file';\nFilesCollaborationsAddCommand.examples = [\n\t'box files:collaborations:add 11111 --role editor --user-id 22222',\n];\n\nFilesCollaborationsAddCommand.flags = {\n\t...CollaborationsCreateCommand.flags,\n};\n\nFilesCollaborationsAddCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to add a collaboration to',\n\t}),\n};\n\nmodule.exports = FilesCollaborationsAddCommand;\n"
  },
  {
    "path": "src/commands/files/collaborations/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Args } = require('@oclif/core');\nconst PaginationUtilities = require('../../../pagination-utils');\n\nclass FilesCollaborationsListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tFilesCollaborationsListCommand\n\t\t);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet collaborations = await this.client.files.getCollaborations(\n\t\t\targs.id,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(collaborations);\n\t}\n}\n\nFilesCollaborationsListCommand.aliases = ['files:collaborations:list'];\n\nFilesCollaborationsListCommand.description =\n\t'List all collaborations on a file';\nFilesCollaborationsListCommand.examples = ['box files:collaborations 11111'];\nFilesCollaborationsListCommand._endpoint = 'get_files_id_collaborations';\n\nFilesCollaborationsListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nFilesCollaborationsListCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to get collaborations for',\n\t}),\n};\n\nmodule.exports = FilesCollaborationsListCommand;\n"
  },
  {
    "path": "src/commands/files/comments.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass CommentsListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(CommentsListCommand);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet comments = await this.client.files.getComments(args.id, options);\n\t\tawait this.output(comments);\n\t}\n}\n\nCommentsListCommand.aliases = ['comments:list'];\n\nCommentsListCommand.description = 'List all comments on a file';\nCommentsListCommand.examples = ['box files:comments 11111'];\nCommentsListCommand._endpoint = 'get_files_id_comments';\n\nCommentsListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.pagingFlag,\n};\n\nCommentsListCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to get comments for',\n\t}),\n};\n\nmodule.exports = CommentsListCommand;\n"
  },
  {
    "path": "src/commands/files/copy.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass FilesCopyCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesCopyCommand);\n\t\tlet options = {};\n\n\t\tif (flags.name) {\n\t\t\toptions.name = flags.name;\n\t\t}\n\t\tif (flags.version) {\n\t\t\toptions.version = flags.version;\n\t\t}\n\n\t\tlet fileCopy = await this.client.files.copy(\n\t\t\targs.id,\n\t\t\targs.parentID,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(fileCopy);\n\t}\n}\n\nFilesCopyCommand.description = 'Copy a file to a different folder';\nFilesCopyCommand.examples = ['box files:copy 11111 22222'];\nFilesCopyCommand._endpoint = 'post_files_id_copy';\n\nFilesCopyCommand.flags = {\n\t...BoxCommand.flags,\n\tname: Flags.string({ description: 'New name for the file' }),\n\tversion: Flags.string({\n\t\tdescription:\n\t\t\t'File version ID if you want to copy a specific file version',\n\t}),\n\t'id-only': Flags.boolean({\n\t\tdescription: 'Output only the ID of the file copy ',\n\t}),\n};\n\nFilesCopyCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to copy',\n\t}),\n\tparentID: Args.string({\n\t\tname: 'parentID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the new parent folder to copy the file into',\n\t}),\n};\n\nmodule.exports = FilesCopyCommand;\n"
  },
  {
    "path": "src/commands/files/delete.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass FilesDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesDeleteCommand);\n\n\t\tlet options = flags.etag ? { etag: flags.etag } : null;\n\n\t\tawait this.client.files.delete(args.id, options);\n\n\t\tif (flags.force) {\n\t\t\ttry {\n\t\t\t\tawait this.client.files.deletePermanently(args.id);\n\t\t\t} catch (error) {\n\t\t\t\t// If the item can't be found in the trash, assume that it was already deleted or\n\t\t\t\t// that the enterprise didn't have trash enabled.  This should be regarded as a success case.\n\t\t\t\tif (error.statusCode !== 404) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.info(\n\t\t\t`Deleted file ${args.id}${flags.force ? ' permanently' : ''}`\n\t\t);\n\t}\n}\n\nFilesDeleteCommand.description = 'Delete a file';\nFilesDeleteCommand.examples = ['box files:delete 11111'];\nFilesDeleteCommand._endpoint = 'delete_files_id';\n\nFilesDeleteCommand.flags = {\n\t...BoxCommand.flags,\n\tforce: Flags.boolean({\n\t\tchar: 'f',\n\t\tdescription: 'Permanently delete the item, bypassing the trash',\n\t}),\n\tetag: Flags.string({ description: 'Only delete if etag value matches' }),\n};\n\nFilesDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to delete',\n\t}),\n};\n\nmodule.exports = FilesDeleteCommand;\n"
  },
  {
    "path": "src/commands/files/download.js",
    "content": "'use strict';\n\nconst { Flags, Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\nconst fs = require('node:fs');\nconst path = require('node:path');\nconst progress = require('cli-progress');\nconst BoxCLIError = require('../../cli-error');\nconst utils = require('../../util');\n\nclass FilesDownloadCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesDownloadCommand);\n\n\t\tlet file = await this.client.files.get(args.id);\n\t\tlet fileName = flags['save-as'] || file.name;\n\n\t\tlet filePath;\n\n\t\tif (flags.destination) {\n\t\t\tawait utils.checkDir(flags.destination, flags['create-path']);\n\t\t\tfilePath = path.join(flags.destination, fileName);\n\t\t} else {\n\t\t\tfilePath = path.join(\n\t\t\t\tthis.settings.boxDownloadsFolderPath,\n\t\t\t\tfileName\n\t\t\t);\n\t\t}\n\n\t\tif (!flags.overwrite && fs.existsSync(filePath)) {\n\t\t\tif (flags.overwrite === false) {\n\t\t\t\tthis.info(\n\t\t\t\t\t`Downloading the file will not occur because the file ${filePath} already exists, and the --no-overwrite flag is set.`\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet shouldOverwrite = await this.confirm(\n\t\t\t\t`File ${filePath} already exists. Overwrite? (Use --overwrite or -y to skip this prompt.)`\n\t\t\t);\n\n\t\t\tif (!shouldOverwrite) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tlet options = {};\n\n\t\tif (flags.version) {\n\t\t\toptions.version = flags.version;\n\t\t}\n\n\t\tlet stream = await this.client.files.getReadStream(args.id, options);\n\t\tlet output;\n\t\ttry {\n\t\t\toutput = fs.createWriteStream(filePath);\n\t\t\tstream.pipe(output);\n\t\t} catch (error) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t`Could not download to destination file ${filePath}`,\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\n\t\tlet progressBar = new progress.Bar({\n\t\t\tformat: '[{bar}] {percentage}% | ETA: {eta_formatted} | {value}/{total} | Speed: {speed} MB/s',\n\t\t\tstopOnComplete: true,\n\t\t});\n\t\tlet startTime = Date.now();\n\t\tprogressBar.start(file.size, 0, { speed: 'N/A' });\n\n\t\tlet downloadedByte = 0;\n\t\tstream.on('data', (chunk) => {\n\t\t\tdownloadedByte += chunk.length;\n\t\t});\n\t\tlet intervalUpdate = setInterval(() => {\n\t\t\tprogressBar.update(downloadedByte, {\n\t\t\t\tspeed: Math.floor(\n\t\t\t\t\tdownloadedByte / (Date.now() - startTime) / 1000\n\t\t\t\t),\n\t\t\t});\n\t\t}, 1000);\n\n\t\t// We need to await the end of the stream to avoid a race condition here\n\t\tawait new Promise((resolve, reject) => {\n\t\t\toutput.on('close', resolve);\n\t\t\tstream.on('error', reject);\n\t\t});\n\t\tclearInterval(intervalUpdate);\n\t\tprogressBar.update(downloadedByte);\n\t\tthis.info(`Downloaded file ${fileName}`);\n\t}\n}\n\nFilesDownloadCommand.description = 'Download a file';\nFilesDownloadCommand.examples = [\n\t'box files:download 11111 --destination /path/to/destinationFolder',\n];\nFilesDownloadCommand._endpoint = 'get_files_id_content';\n\nFilesDownloadCommand.flags = {\n\t...BoxCommand.flags,\n\tversion: Flags.string({\n\t\tdescription: 'File version ID of the specific file version to download',\n\t}),\n\tdestination: Flags.string({\n\t\tdescription: 'The destination folder to write the file to',\n\t\tparse: utils.parsePath,\n\t}),\n\t'create-path': Flags.boolean({\n\t\tdescription:\n\t\t\t'Recursively creates a path to a directory if it does not exist',\n\t\tallowNo: true,\n\t\tdefault: true,\n\t}),\n\toverwrite: Flags.boolean({\n\t\tdescription:\n\t\t\t'Overwrite a file if it already exists (prevents overwrite prompt)',\n\t\tallowNo: true,\n\t}),\n\t'save-as': Flags.string({\n\t\tdescription: 'The filename used when saving the file',\n\t}),\n};\n\nFilesDownloadCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to download',\n\t}),\n};\n\nmodule.exports = FilesDownloadCommand;\n"
  },
  {
    "path": "src/commands/files/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass FilesGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesGetCommand);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet file = await this.client.files.get(args.id, options);\n\t\tawait this.output(file);\n\t}\n}\n\nFilesGetCommand.description = 'Get information about a file';\nFilesGetCommand.examples = ['box files:get 11111'];\nFilesGetCommand._endpoint = 'get_files_id';\n\nFilesGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nFilesGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to get',\n\t}),\n};\n\nmodule.exports = FilesGetCommand;\n"
  },
  {
    "path": "src/commands/files/lock.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass FilesLockCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesLockCommand);\n\t\tlet options = {};\n\n\t\tif (flags.expires) {\n\t\t\toptions.expires_at = flags.expires;\n\t\t}\n\t\tif (Object.hasOwn(flags, 'prevent-download')) {\n\t\t\toptions.is_download_prevented = flags['prevent-download'];\n\t\t}\n\n\t\tlet file = await this.client.files.lock(args.id, options);\n\t\tawait this.output(file);\n\t}\n}\n\nFilesLockCommand.aliases = ['files:update-lock'];\n\nFilesLockCommand.description = 'Lock a file';\nFilesLockCommand.examples = ['box files:lock 11111'];\nFilesLockCommand._endpoint = 'put_files_id lock';\n\nFilesLockCommand.flags = {\n\t...BoxCommand.flags,\n\texpires: Flags.string({\n\t\tdescription:\n\t\t\t'Make the lock expire from a timespan set from now. Use s for seconds, m for minutes, h for hours, d for days, w for weeks, M for months. For example, 30 seconds is 30s',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'prevent-download': Flags.boolean({\n\t\tdescription: 'Prevent download of locked file',\n\t\tallowNo: true,\n\t}),\n};\n\nFilesLockCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of file to lock',\n\t}),\n};\n\nmodule.exports = FilesLockCommand;\n"
  },
  {
    "path": "src/commands/files/metadata/add.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../../util');\n\nclass FilesCreateMetadataCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesCreateMetadataCommand);\n\n\t\tlet metadataValues = Object.assign({}, ...flags.data);\n\n\t\tlet metadata = await this.client.files.addMetadata(\n\t\t\targs.id,\n\t\t\tflags.scope,\n\t\t\tflags['template-key'],\n\t\t\tmetadataValues\n\t\t);\n\t\tawait this.output(metadata);\n\t}\n}\n\nFilesCreateMetadataCommand.aliases = ['files:metadata:create'];\n\nFilesCreateMetadataCommand.description = 'Add metadata to a file';\nFilesCreateMetadataCommand.examples = [\n\t'box files:metadata:add 11111 --template-key employeeRecord --data \"name=John Doe\" --data department=Sales',\n\t'box files:metadata:add 22222 --template-key myTemplate --data \"multiselectkey1=[option1A,option1B]\" --data \"multiselectkey2=[option2A]\"',\n];\nFilesCreateMetadataCommand._endpoint = 'post_files_id_metadata_id_id';\n\nFilesCreateMetadataCommand.flags = {\n\t...BoxCommand.flags,\n\tdata: Flags.string({\n\t\tdescription:\n\t\t\t'Metadata key and value, in the form \"key=value\".  Note: For float type, use \"#\" at the beginning of digits: key2=#1234.50',\n\t\tmultiple: true,\n\t\trequired: true,\n\t\tparse: utilities.parseMetadata,\n\t}),\n\tscope: Flags.string({\n\t\tdescription: 'The scope of the metadata template to use',\n\t\tdefault: 'enterprise',\n\t}),\n\t'template-key': Flags.string({\n\t\tdescription: 'The key of the metadata template to use',\n\t\trequired: true,\n\t}),\n};\n\nFilesCreateMetadataCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to add metadata to',\n\t}),\n};\n\nmodule.exports = FilesCreateMetadataCommand;\n"
  },
  {
    "path": "src/commands/files/metadata/get.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass FilesGetMetadataCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesGetMetadataCommand);\n\n\t\tlet metadata = await this.client.files.getMetadata(\n\t\t\targs.id,\n\t\t\tflags.scope,\n\t\t\tflags['template-key']\n\t\t);\n\t\tawait this.output(metadata);\n\t}\n}\n\nFilesGetMetadataCommand.description = 'Get information about a metadata object';\nFilesGetMetadataCommand.examples = [\n\t'box files:metadata:get 11111 --template-key employeeRecord',\n];\nFilesGetMetadataCommand._endpoint = 'get_files_id_metadata_id_id';\n\nFilesGetMetadataCommand.flags = {\n\t...BoxCommand.flags,\n\tscope: Flags.string({\n\t\tdescription: 'The scope of the metadata template to retrieve',\n\t\tdefault: 'enterprise',\n\t}),\n\t'template-key': Flags.string({\n\t\tdescription: 'The key of the metadata template to retrieve',\n\t\trequired: true,\n\t}),\n};\n\nFilesGetMetadataCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to get metadata on',\n\t}),\n};\n\nmodule.exports = FilesGetMetadataCommand;\n"
  },
  {
    "path": "src/commands/files/metadata/index.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass FilesGetAllMetadataCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(FilesGetAllMetadataCommand);\n\n\t\tlet metadata = await this.client.files.getAllMetadata(args.id);\n\t\tawait this.output(metadata);\n\t}\n}\n\nFilesGetAllMetadataCommand.aliases = ['files:metadata:get-all'];\n\nFilesGetAllMetadataCommand.description = 'Get all metadata on a file';\nFilesGetAllMetadataCommand.examples = ['box files:metadata 11111'];\nFilesGetAllMetadataCommand._endpoint = 'get_files_id_metadata';\n\nFilesGetAllMetadataCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nFilesGetAllMetadataCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Id of the file',\n\t}),\n};\n\nmodule.exports = FilesGetAllMetadataCommand;\n"
  },
  {
    "path": "src/commands/files/metadata/remove.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass FilesDeleteMetadataCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesDeleteMetadataCommand);\n\n\t\tawait this.client.files.deleteMetadata(\n\t\t\targs.id,\n\t\t\tflags.scope,\n\t\t\tflags['template-key']\n\t\t);\n\t\tthis.info(`Successfully deleted metadata ${flags['template-key']}`);\n\t}\n}\n\nFilesDeleteMetadataCommand.aliases = ['files:metadata:delete'];\n\nFilesDeleteMetadataCommand.description = 'Delete metadata from a file';\nFilesDeleteMetadataCommand.examples = [\n\t'box files:metadata:remove 11111 --scope global --template-key properties',\n];\nFilesDeleteMetadataCommand._endpoint = 'delete_files_id_metadata_id_id';\n\nFilesDeleteMetadataCommand.flags = {\n\t...BoxCommand.flags,\n\tscope: Flags.string({\n\t\tdescription: 'The scope of the metadata template to remove',\n\t\tdefault: 'enterprise',\n\t}),\n\t'template-key': Flags.string({\n\t\tdescription: 'The key of the metadata template to remove',\n\t\trequired: true,\n\t}),\n};\n\nFilesDeleteMetadataCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to remove metadata from',\n\t}),\n};\n\nmodule.exports = FilesDeleteMetadataCommand;\n"
  },
  {
    "path": "src/commands/files/metadata/set.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../../util');\n\nclass FilesSetMetadataCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesSetMetadataCommand);\n\n\t\tlet metadataValues = Object.assign({}, ...flags.data);\n\t\tlet templateKey = flags['template-key'];\n\n\t\tlet metadata = await this.client.files.setMetadata(\n\t\t\targs.id,\n\t\t\tflags.scope,\n\t\t\ttemplateKey,\n\t\t\tmetadataValues\n\t\t);\n\t\tawait this.output(metadata);\n\t}\n}\n\nFilesSetMetadataCommand.description = 'Set metadata on a file';\nFilesSetMetadataCommand.examples = [\n\t'box files:metadata:set 11111 --template-key employeeRecord --data \"name=John Doe\" --data department=Sales',\n\t'box files:metadata:set 22222 --template-key myTemplate --data \"multiselectkey1=[option1A,option1B]\" --data \"multiselectkey2=[option2A]\"',\n];\n\nFilesSetMetadataCommand.flags = {\n\t...BoxCommand.flags,\n\tdata: Flags.string({\n\t\tdescription:\n\t\t\t'Metadata key and value, in the form \"key=value\".  Note: For float type, use \"#\" at the beginning of digits: key2=#1234.50',\n\t\trequired: true,\n\t\tmultiple: true,\n\t\tparse: utilities.parseMetadata,\n\t}),\n\tscope: Flags.string({\n\t\tdescription: 'The scope of the metadata template to use',\n\t\tdefault: 'enterprise',\n\t}),\n\t'template-key': Flags.string({\n\t\tdescription: 'The key of the metadata template to use',\n\t\trequired: true,\n\t}),\n};\n\nFilesSetMetadataCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to add metadata to',\n\t}),\n};\n\nmodule.exports = FilesSetMetadataCommand;\n"
  },
  {
    "path": "src/commands/files/metadata/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../../util');\n\nconst OP_FLAGS = Object.freeze({\n\tadd: true,\n\tcopy: true,\n\tmove: true,\n\tremove: true,\n\treplace: true,\n\ttest: true,\n});\n\nclass FilesUpdateMetadataCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args, raw } = await this.parse(\n\t\t\tFilesUpdateMetadataCommand\n\t\t);\n\n\t\tlet updates = raw\n\t\t\t.filter((v) => v.type === 'flag' && OP_FLAGS[v.flag])\n\t\t\t.map((op) => {\n\t\t\t\tlet opName = op.flag;\n\t\t\t\tlet opData = flags[op.flag].shift();\n\n\t\t\t\treturn { op: opName, ...opData };\n\t\t\t});\n\n\t\tlet metadata = await this.client.files.updateMetadata(\n\t\t\targs.id,\n\t\t\tflags.scope,\n\t\t\tflags['template-key'],\n\t\t\tupdates\n\t\t);\n\t\tawait this.output(metadata);\n\t}\n}\n\nFilesUpdateMetadataCommand.description =\n\t'Update the metadata attached to a file';\nFilesUpdateMetadataCommand.examples = [\n\t'box files:metadata:update 11111 --template-key employeeRecord --replace department=Finance',\n];\nFilesUpdateMetadataCommand._endpoint = 'put_files_id_metadata_id_id';\n\nFilesUpdateMetadataCommand.flags = {\n\t...BoxCommand.flags,\n\tscope: Flags.string({\n\t\tdescription: 'The scope of the metadata template to update against',\n\t\tdefault: 'enterprise',\n\t}),\n\t'template-key': Flags.string({\n\t\tdescription: 'The key of the metadata template to update against',\n\t\trequired: true,\n\t}),\n\tadd: Flags.string({\n\t\tchar: 'a',\n\t\tdescription:\n\t\t\t'Add a key to the metadata document; must be in the form key=value',\n\t\tmultiple: true,\n\t\tparse: utilities.parseMetadataOp,\n\t}),\n\tcopy: Flags.string({\n\t\tchar: 'c',\n\t\tdescription:\n\t\t\t'Copy a metadata value to another key; must be in the form sourceKey>destinationKey',\n\t\tmultiple: true,\n\t\tparse: utilities.parseMetadataOp,\n\t}),\n\tmove: Flags.string({\n\t\tchar: 'm',\n\t\tdescription:\n\t\t\t'Move a metadata value from one key to another; must be in the form sourceKey>destinationKey',\n\t\tmultiple: true,\n\t\tparse: utilities.parseMetadataOp,\n\t}),\n\tremove: Flags.string({\n\t\tdescription: 'Remove a key from the metadata document',\n\t\tmultiple: true,\n\t\tparse: utilities.parseMetadataOp,\n\t}),\n\treplace: Flags.string({\n\t\tdescription:\n\t\t\t'Replace the value of an existing metadata key; must be in the form key=value',\n\t\tmultiple: true,\n\t\tparse: utilities.parseMetadataOp,\n\t}),\n\ttest: Flags.string({\n\t\tchar: 'T',\n\t\tdescription:\n\t\t\t'Test that a metadata key contains a specific value; must be in the form key=value',\n\t\tmultiple: true,\n\t\tparse: utilities.parseMetadataOp,\n\t}),\n};\n\nFilesUpdateMetadataCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to update metadata on',\n\t}),\n};\n\nmodule.exports = FilesUpdateMetadataCommand;\n"
  },
  {
    "path": "src/commands/files/move.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass FilesMoveCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesMoveCommand);\n\t\tlet updates = {\n\t\t\tparent: {\n\t\t\t\tid: args.parentID,\n\t\t\t},\n\t\t};\n\n\t\tif (flags.etag) {\n\t\t\tupdates.etag = flags.etag;\n\t\t}\n\n\t\tlet movedFile = await this.client.files.update(args.id, updates);\n\t\tawait this.output(movedFile);\n\t}\n}\n\nFilesMoveCommand.description = 'Move a file to a different folder';\nFilesMoveCommand.examples = ['box files:move 11111 22222'];\nFilesMoveCommand._endpoint = 'put_files_id move';\n\nFilesMoveCommand.flags = {\n\t...BoxCommand.flags,\n\tetag: Flags.string({ description: 'Only move if etag value matches' }),\n};\n\nFilesMoveCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to move',\n\t}),\n\tparentID: Args.string({\n\t\tname: 'parentID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the new parent folder to move the file into',\n\t}),\n};\n\nmodule.exports = FilesMoveCommand;\n"
  },
  {
    "path": "src/commands/files/rename.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass FilesRenameCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesRenameCommand);\n\t\tlet options = {\n\t\t\tname: args.name,\n\t\t};\n\n\t\tif (Object.hasOwn(flags, 'description')) {\n\t\t\toptions.description = flags.description;\n\t\t}\n\n\t\tif (flags.etag) {\n\t\t\toptions.etag = flags.etag;\n\t\t}\n\n\t\tlet file = await this.client.files.update(args.id, options);\n\t\tawait this.output(file);\n\t}\n}\n\nFilesRenameCommand.description = 'Rename a file';\nFilesRenameCommand.examples = ['box files:rename 11111 \"New File Name.pdf\"'];\n\nFilesRenameCommand.flags = {\n\t...BoxCommand.flags,\n\tdescription: Flags.string({\n\t\tdescription: 'Change the file description',\n\t\tparse: utilities.unescapeSlashes,\n\t}),\n\tetag: Flags.string({ description: 'Only rename if etag value matches' }),\n};\n\nFilesRenameCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of file to rename',\n\t}),\n\tname: Args.string({\n\t\tname: 'name',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'New name of file',\n\t}),\n};\n\nmodule.exports = FilesRenameCommand;\n"
  },
  {
    "path": "src/commands/files/share.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Args } = require('@oclif/core');\nconst {\n\tsharedLinkFlags,\n\tsharedLinkFileFlags,\n} = require('../shared-links/create');\nconst SharedLinksModule = require('../../modules/shared-links');\n\nclass FilesShareCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args, flags } = await this.parse(FilesShareCommand);\n\n\t\t// Transform arguments for generic module\n\t\targs.itemType = 'file';\n\t\targs.itemID = args.id;\n\t\tdelete args.id;\n\n\t\tlet sharedLinksModule = new SharedLinksModule(this.client);\n\t\tlet updatedItem = await sharedLinksModule.createSharedLink(args, flags);\n\t\tawait this.output(updatedItem);\n\t}\n}\n\nFilesShareCommand.aliases = [\n\t'files:shared-links:create',\n\t'files:shared-links:update',\n];\n\nFilesShareCommand.description = 'Create a shared link for a file';\nFilesShareCommand.examples = [\n\t'box files:share 11111 --access company --vanity-name my-custom-name-123',\n];\nFilesShareCommand._endpoint = 'put_files_id create_shared_link';\n\nFilesShareCommand.flags = {\n\t...sharedLinkFlags,\n\t...sharedLinkFileFlags,\n};\n\nFilesShareCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to share',\n\t}),\n};\n\nmodule.exports = FilesShareCommand;\n"
  },
  {
    "path": "src/commands/files/tasks/index.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass FilesListTasksCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesListTasksCommand);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet tasks = await this.client.files.getTasks(args.id, options);\n\t\tawait this.output(tasks);\n\t}\n}\n\nFilesListTasksCommand.aliases = ['files:tasks:list'];\n\nFilesListTasksCommand.description = 'List all tasks on this file';\nFilesListTasksCommand.examples = ['box files:tasks 11111'];\nFilesListTasksCommand._endpoint = 'get_files_id_tasks';\n\nFilesListTasksCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nFilesListTasksCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of file on which to retrieve tasks',\n\t}),\n};\n\nmodule.exports = FilesListTasksCommand;\n"
  },
  {
    "path": "src/commands/files/unlock.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass FilesUnlockCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(FilesUnlockCommand);\n\n\t\tlet file = await this.client.files.unlock(args.id);\n\t\tawait this.output(file);\n\t}\n}\n\nFilesUnlockCommand.description = 'Unlock a file';\nFilesUnlockCommand.examples = ['box files:unlock 11111'];\nFilesUnlockCommand._endpoint = 'put_files_id unlock';\n\nFilesUnlockCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nFilesUnlockCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Id of file to unlock',\n\t}),\n};\n\nmodule.exports = FilesUnlockCommand;\n"
  },
  {
    "path": "src/commands/files/unshare.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\nconst SharedLinksDeleteCommand = require('../shared-links/delete');\nconst SharedLinksModule = require('../../modules/shared-links');\nconst chalk = require('chalk');\n\nclass FilesUnshareCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(FilesUnshareCommand);\n\n\t\t// Transform arguments for generic module\n\t\targs.itemType = 'file';\n\t\targs.itemID = args.id;\n\t\tdelete args.id;\n\n\t\tlet sharedLinksModule = new SharedLinksModule(this.client);\n\t\tlet item = await sharedLinksModule.removeSharedLink(args);\n\t\tthis.info(\n\t\t\tchalk`{green Removed shared link from ${args.itemType} \"${item.name}\"}`\n\t\t);\n\t}\n}\n\nFilesUnshareCommand.aliases = ['files:shared-links:delete'];\n\nFilesUnshareCommand.description = 'Delete a shared link for a file';\nFilesUnshareCommand.examples = ['box files:unshare 11111'];\nFilesUnshareCommand._endpoint = 'put_files_id delete_shared_link';\n\nFilesUnshareCommand.flags = {\n\t...SharedLinksDeleteCommand.flags,\n};\n\nFilesUnshareCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to unshare',\n\t}),\n};\n\nmodule.exports = FilesUnshareCommand;\n"
  },
  {
    "path": "src/commands/files/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass FileUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FileUpdateCommand);\n\t\tlet updates = {};\n\n\t\tif (flags.name) {\n\t\t\tupdates.name = flags.name;\n\t\t}\n\t\tif (Object.hasOwn(flags, 'description')) {\n\t\t\tupdates.description = flags.description;\n\t\t}\n\t\tif (flags.tags) {\n\t\t\tupdates.tags = flags.tags.split(',');\n\t\t}\n\n\t\tif (flags.etag) {\n\t\t\tupdates.etag = flags.etag;\n\t\t}\n\n\t\tif (flags['disposition-at']) {\n\t\t\tupdates.disposition_at = flags['disposition-at'];\n\t\t}\n\n\t\tlet updatedFile = await this.client.files.update(args.id, updates);\n\t\tawait this.output(updatedFile);\n\t}\n}\n\nFileUpdateCommand.description = 'Update a file record';\nFileUpdateCommand.examples = [\n\t'box files:update 11111 --name \"New File Name.pdf\"',\n];\nFileUpdateCommand._endpoint = 'put_files_id';\n\nFileUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\tname: Flags.string({ description: 'New name for the file' }),\n\tdescription: Flags.string({\n\t\tdescription: 'New description for the file',\n\t\tparse: utilities.unescapeSlashes,\n\t}),\n\ttags: Flags.string({\n\t\tdescription: 'Set tags on the file, specified as comma-separated tags',\n\t}),\n\tetag: Flags.string({\n\t\tdescription: 'Only apply updates if the ETag value matches',\n\t}),\n\t'disposition-at': Flags.string({\n\t\tdescription:\n\t\t\t'The retention expiration timestamp for the given file. This date cannot be shortened once set on a file',\n\t}),\n};\n\nFileUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to update',\n\t}),\n};\n\nmodule.exports = FileUpdateCommand;\n"
  },
  {
    "path": "src/commands/files/upload.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst fs = require('node:fs');\nconst path = require('node:path');\nconst BoxCLIError = require('../../cli-error');\nconst {\n\tcreateReadStream,\n\tuploadFile,\n\tuploadNewFileVersion,\n} = require('../../modules/upload');\nconst DEBUG = require('../../debug');\n\nclass FilesUploadCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesUploadCommand);\n\t\tif (!fs.existsSync(args.path)) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t`File not found: ${args.path}. Please check the file path and try again.`\n\t\t\t);\n\t\t}\n\t\tlet size = fs.statSync(args.path).size;\n\t\tlet folderID = flags['parent-id'];\n\t\tlet stream = createReadStream(args.path);\n\t\tlet fileAttributes = {};\n\t\tlet name;\n\n\t\tname = flags.name || path.basename(args.path);\n\t\tif (flags['content-created-at']) {\n\t\t\tfileAttributes.content_created_at = flags['content-created-at'];\n\t\t}\n\t\tif (flags['content-modified-at']) {\n\t\t\tfileAttributes.content_modified_at = flags['content-modified-at'];\n\t\t}\n\n\t\tlet file;\n\t\ttry {\n\t\t\tfile = await uploadFile(this.client, {\n\t\t\t\tfolderID,\n\t\t\t\tname,\n\t\t\t\tstream,\n\t\t\t\tsize,\n\t\t\t\tfileAttributes,\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tconst { statusCode, response } = error;\n\t\t\tconst body = response?.body;\n\n\t\t\tif (\n\t\t\t\t!flags.overwrite ||\n\t\t\t\tstatusCode !== 409 ||\n\t\t\t\tbody?.code !== 'item_name_in_use'\n\t\t\t) {\n\t\t\t\tif (\n\t\t\t\t\t!flags.overwrite &&\n\t\t\t\t\tstatusCode === 409 &&\n\t\t\t\t\tbody?.code === 'item_name_in_use'\n\t\t\t\t) {\n\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t'A file with the same name already exists in the destination folder. Use --overwrite to replace it with a new version.',\n\t\t\t\t\t\terror\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tconst conflicts = body.context_info?.conflicts;\n\t\t\tconst existingFileID = Array.isArray(conflicts)\n\t\t\t\t? conflicts?.[0]?.id\n\t\t\t\t: conflicts?.id;\n\n\t\t\tif (!existingFileID) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t'File already exists but could not determine the existing file ID from the conflict response. Try uploading a new version manually with files:versions:upload.'\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tDEBUG.output(\n\t\t\t\t`File already exists in folder; uploading as new version of file ${existingFileID}`\n\t\t\t);\n\n\t\t\t// Re-create the stream since the first attempt consumed it\n\t\t\tconst versionStream = createReadStream(args.path);\n\n\t\t\tfile = await uploadNewFileVersion(this.client, {\n\t\t\t\tfileID: existingFileID,\n\t\t\t\tstream: versionStream,\n\t\t\t\tsize,\n\t\t\t\tfileAttributes,\n\t\t\t});\n\t\t}\n\n\t\tawait this.output(file.entries[0]);\n\t}\n}\n\nFilesUploadCommand.description =\n\t'Upload a file to a folder. Use --overwrite to automatically replace an existing file with the same name by uploading a new version';\nFilesUploadCommand.examples = [\n\t'box files:upload /path/to/file.pdf --parent-id 22222',\n\t'box files:upload /path/to/file.pdf --parent-id 22222 --overwrite',\n];\nFilesUploadCommand._endpoint = 'post_files_content';\n\nFilesUploadCommand.flags = {\n\t...BoxCommand.flags,\n\t'parent-id': Flags.string({\n\t\tchar: 'p',\n\t\tdescription:\n\t\t\t'ID of the parent folder to upload the file to; defaults to the root folder',\n\t\tdefault: '0',\n\t}),\n\tname: Flags.string({\n\t\tchar: 'n',\n\t\tdescription: 'Provide different name for uploaded file',\n\t}),\n\t'content-created-at': Flags.string({\n\t\tdescription:\n\t\t\t'The creation date of the file content. Use a timestamp or shorthand syntax 0t, like 5w for 5 weeks. Not supported with --overwrite',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'content-modified-at': Flags.string({\n\t\tdescription:\n\t\t\t'The modification date of the file content. Use a timestamp or shorthand syntax 0t, like 5w for 5 weeks',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'id-only': Flags.boolean({\n\t\tdescription: 'Return only an ID to output from this command',\n\t}),\n\toverwrite: Flags.boolean({\n\t\tdescription:\n\t\t\t'Overwrite the file if it already exists in the destination folder, by uploading a new file version',\n\t}),\n};\n\nFilesUploadCommand.args = {\n\tpath: Args.string({\n\t\tname: 'path',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Path to the file to be uploaded',\n\t}),\n};\n\nmodule.exports = FilesUploadCommand;\n"
  },
  {
    "path": "src/commands/files/versions/delete.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass FilesDeleteVersionsCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesDeleteVersionsCommand);\n\n\t\tlet options = flags.etag ? { etag: flags.etag } : null;\n\n\t\tawait this.client.files.deleteVersion(\n\t\t\targs.fileID,\n\t\t\targs.fileVersionID,\n\t\t\toptions\n\t\t);\n\t\tthis.info(\n\t\t\t`Deleted file version ${args.fileVersionID} from file ${args.fileID}`\n\t\t);\n\t}\n}\n\nFilesDeleteVersionsCommand.description = 'Delete a file version';\nFilesDeleteVersionsCommand.examples = ['box files:versions:delete 11111 55555'];\nFilesDeleteVersionsCommand._endpoint = 'delete_files_id_versions_id';\n\nFilesDeleteVersionsCommand.flags = {\n\t...BoxCommand.flags,\n\tetag: Flags.string({ description: 'Only delete if etag value matches' }),\n};\n\nFilesDeleteVersionsCommand.args = {\n\tfileID: Args.string({\n\t\tname: 'fileID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to get versions for',\n\t}),\n\tfileVersionID: Args.string({\n\t\tname: 'fileVersionID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file version to delete',\n\t}),\n};\n\nmodule.exports = FilesDeleteVersionsCommand;\n"
  },
  {
    "path": "src/commands/files/versions/download.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\nconst FilesDownloadCommand = require('../download');\nconst BoxCLIError = require('../../../cli-error');\nconst _ = require('lodash');\nconst path = require('node:path');\nconst fs = require('node:fs');\nconst utilities = require('../../../util');\n\nclass FilesVersionsDownloadCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesVersionsDownloadCommand);\n\n\t\tlet file = await this.client.files.get(args.fileID);\n\t\tlet fileName = flags['save-as'] || file.name;\n\n\t\tlet filePath;\n\n\t\tif (flags.destination) {\n\t\t\tawait utilities.checkDir(flags.destination, flags['create-path']);\n\t\t\tfilePath = path.join(flags.destination, fileName);\n\t\t} else {\n\t\t\tfilePath = path.join(\n\t\t\t\tthis.settings.boxDownloadsFolderPath,\n\t\t\t\tfileName\n\t\t\t);\n\t\t}\n\n\t\tif (!flags.overwrite && fs.existsSync(filePath)) {\n\t\t\tif (flags.overwrite === false) {\n\t\t\t\tthis.info(\n\t\t\t\t\t`Downloading the file will not occur because the file ${filePath} already exists, and the --no-overwrite flag is set.`\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet shouldOverwrite = await this.confirm(\n\t\t\t\t`File ${filePath} already exists — overwrite?`\n\t\t\t);\n\n\t\t\tif (!shouldOverwrite) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tlet options = { version: args.fileVersionID };\n\n\t\tlet stream = await this.client.files.getReadStream(\n\t\t\targs.fileID,\n\t\t\toptions\n\t\t);\n\t\tlet output;\n\t\ttry {\n\t\t\toutput = fs.createWriteStream(filePath);\n\t\t\tstream.pipe(output);\n\t\t} catch (error) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t`Could not download to destination file ${filePath}`,\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\n\t\t// @TODO(2018-09-18): Add progress bar for large downloads\n\n\t\t// We need to await the end of the stream to avoid a race condition here\n\t\tawait new Promise((resolve, reject) => {\n\t\t\toutput.on('close', resolve);\n\t\t\tstream.on('error', reject);\n\t\t});\n\t\tthis.info(`Downloaded file ${fileName}`);\n\t}\n}\n\nFilesVersionsDownloadCommand.description =\n\t'Download a specific version of a file';\nFilesVersionsDownloadCommand.examples = [\n\t'box files:versions:download 11111 55555',\n];\n\nFilesVersionsDownloadCommand.flags = {\n\t..._.omit(FilesDownloadCommand.flags, 'version'),\n};\n\nFilesVersionsDownloadCommand.args = {\n\tfileID: Args.string({\n\t\tname: 'fileID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to download',\n\t}),\n\tfileVersionID: Args.string({\n\t\tname: 'fileVersionID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of file version to download',\n\t}),\n};\n\nmodule.exports = FilesVersionsDownloadCommand;\n"
  },
  {
    "path": "src/commands/files/versions/index.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\nconst PaginationUtilities = require('../../../pagination-utils');\n\nclass FilesListVersionsCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesListVersionsCommand);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet versions = await this.client.files.getVersions(\n\t\t\targs.fileID,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(versions);\n\t}\n}\n\nFilesListVersionsCommand.aliases = ['files:versions:list'];\n\nFilesListVersionsCommand.description = 'Get a list of file versions';\nFilesListVersionsCommand.examples = ['box files:versions 11111'];\nFilesListVersionsCommand._endpoint = 'get_files_id_versions';\n\nFilesListVersionsCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nFilesListVersionsCommand.args = {\n\tfileID: Args.string({\n\t\tname: 'fileID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of file to get versions for',\n\t}),\n};\n\nmodule.exports = FilesListVersionsCommand;\n"
  },
  {
    "path": "src/commands/files/versions/promote.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass FilesPromoteVersionsCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(FilesPromoteVersionsCommand);\n\n\t\tlet version = await this.client.files.promoteVersion(\n\t\t\targs.fileID,\n\t\t\targs.fileVersionID\n\t\t);\n\t\tawait this.output(version);\n\t}\n}\n\nFilesPromoteVersionsCommand.description = 'Promote a file version';\nFilesPromoteVersionsCommand.examples = [\n\t'box files:versions:promote 11111 55555',\n];\nFilesPromoteVersionsCommand._endpoint = 'post_files_id_versions_current';\n\nFilesPromoteVersionsCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nFilesPromoteVersionsCommand.args = {\n\tfileID: Args.string({\n\t\tname: 'fileID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to get versions for',\n\t}),\n\tfileVersionID: Args.string({\n\t\tname: 'fileVersionID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file version to delete',\n\t}),\n};\n\nmodule.exports = FilesPromoteVersionsCommand;\n"
  },
  {
    "path": "src/commands/files/versions/upload.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst fs = require('node:fs');\nconst {\n\tcreateReadStream,\n\tuploadNewFileVersion,\n} = require('../../../modules/upload');\n\nclass FilesUploadVersionsCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(FilesUploadVersionsCommand);\n\t\tconst { args } = await this.parse(FilesUploadVersionsCommand);\n\t\tconst size = fs.statSync(args.path).size;\n\t\tconst fileAttributes = {};\n\t\tconst stream = createReadStream(args.path);\n\n\t\tif (flags['content-modified-at']) {\n\t\t\tfileAttributes.content_modified_at = flags['content-modified-at'];\n\t\t}\n\t\t// @TODO(2018-08-24): Consider adding --preserve-timestamps flag\n\t\tif (flags.name) {\n\t\t\tfileAttributes.name = flags.name;\n\t\t}\n\n\t\tconst file = await uploadNewFileVersion(this.client, {\n\t\t\tfileID: args.fileID,\n\t\t\tstream,\n\t\t\tsize,\n\t\t\tfileAttributes,\n\t\t});\n\t\tawait this.output(file.entries[0]);\n\t}\n}\n\nFilesUploadVersionsCommand.description = 'Upload a new version of a file';\nFilesUploadVersionsCommand.examples = [\n\t'box files:versions:upload 11111 /path/to/file.pdf',\n];\nFilesUploadVersionsCommand._endpoint = 'post_files_id_content';\n\nFilesUploadVersionsCommand.flags = {\n\t...BoxCommand.flags,\n\t'content-modified-at': Flags.string({\n\t\tdescription:\n\t\t\t'The last modification date of the file version. Use a timestamp or shorthand syntax 0t, like 5w for 5 weeks',\n\t}),\n\tname: Flags.string({\n\t\tchar: 'n',\n\t\tdescription: 'Provide different name for uploaded file',\n\t}),\n};\n\nFilesUploadVersionsCommand.args = {\n\tfileID: Args.string({\n\t\tname: 'fileID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to upload a new version of',\n\t}),\n\tpath: Args.string({\n\t\tname: 'path',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Local path to the file to upload',\n\t}),\n};\n\nmodule.exports = FilesUploadVersionsCommand;\n"
  },
  {
    "path": "src/commands/files/zip.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst fs = require('node:fs');\nconst path = require('node:path');\nconst utilities = require('../../util');\n\nclass FilesZipCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FilesZipCommand);\n\n\t\tlet fileName = args.name;\n\t\tif (!fileName.includes('.zip')) {\n\t\t\tfileName += '.zip';\n\t\t}\n\n\t\tlet filePath;\n\n\t\tif (flags.destination) {\n\t\t\tawait utilities.checkDir(flags.destination, flags['create-path']);\n\t\t\tfilePath = path.join(flags.destination, fileName);\n\t\t} else {\n\t\t\tfilePath = path.join(\n\t\t\t\tthis.settings.boxDownloadsFolderPath,\n\t\t\t\tfileName\n\t\t\t);\n\t\t}\n\n\t\tif (!flags.overwrite && fs.existsSync(filePath)) {\n\t\t\tif (flags.overwrite === false) {\n\t\t\t\tthis.info(\n\t\t\t\t\t`Downloading the file will not occur because the file ${filePath} already exists, and the --no-overwrite flag is set.`\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tlet shouldOverwrite = await this.confirm(\n\t\t\t\t`File ${filePath} already exists — overwrite?`\n\t\t\t);\n\n\t\t\tif (!shouldOverwrite) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tlet output = fs.createWriteStream(filePath);\n\n\t\tlet downloadStatus;\n\t\tlet outputFinished = false;\n\n\t\tawait new Promise((resolve, reject) => {\n\t\t\t/* eslint-disable promise/always-return */\n\t\t\tthis.client.files\n\t\t\t\t.downloadZip(fileName, flags.item, output)\n\t\t\t\t.then((status) => {\n\t\t\t\t\tdownloadStatus = status;\n\t\t\t\t\tif (outputFinished) {\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t}\n\t\t\t\t})\n\t\t\t\t.catch(reject);\n\t\t\toutput.on('close', () => {\n\t\t\t\toutput.close();\n\t\t\t\toutputFinished = true;\n\t\t\t\tif (downloadStatus) {\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t});\n\t\t\toutput.on('error', reject);\n\t\t});\n\t\tawait this.output(downloadStatus);\n\t}\n}\n\nFilesZipCommand.description =\n\t'Create a zip of multiple files and folders and download it';\nFilesZipCommand.examples = [\n\t'box files:zip sample_file.zip --item=file:12421 --item=folder:48291',\n];\nFilesZipCommand._endpoint = 'zip_downloads';\n\nFilesZipCommand.flags = {\n\t...BoxCommand.flags,\n\tdestination: Flags.string({\n\t\tdescription: 'The destination folder to write the zip file to',\n\t\tparse: utilities.parsePath,\n\t}),\n\titem: Flags.string({\n\t\tdescription:\n\t\t\t'Files or folders to be part of zip in the form type:ID (i.e. file:1374652)',\n\t\tmultiple: true,\n\t\trequired: true,\n\t\tparse(value) {\n\t\t\tlet splitValue = value.split(':');\n\t\t\treturn { type: splitValue[0], id: splitValue[1] };\n\t\t},\n\t}),\n\t'create-path': Flags.boolean({\n\t\tdescription:\n\t\t\t'Recursively creates a path to a directory if it does not exist',\n\t\tallowNo: true,\n\t\tdefault: true,\n\t}),\n\toverwrite: Flags.boolean({\n\t\tdescription: 'Overwrite a zip file if it already exists',\n\t\tallowNo: true,\n\t}),\n};\n\nFilesZipCommand.args = {\n\tname: Args.string({\n\t\tname: 'name',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Name of the zip to be created and downloaded',\n\t}),\n};\n\nmodule.exports = FilesZipCommand;\n"
  },
  {
    "path": "src/commands/folders/collaborations/add.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\nconst CollaborationsCreateCommand = require('../../collaborations/create');\nconst CollaborationModule = require('../../../modules/collaboration');\n\nclass FoldersCollaborationsAddCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args, flags } = await this.parse(\n\t\t\tFoldersCollaborationsAddCommand\n\t\t);\n\n\t\t// Transform arguments for generic module\n\t\targs.itemType = 'folder';\n\t\targs.itemID = args.id;\n\t\tdelete args.id;\n\n\t\tlet collabModule = new CollaborationModule(this.client);\n\t\tlet collaboration = await collabModule.createCollaboration(args, flags);\n\t\tawait this.output(collaboration);\n\t}\n}\n\nFoldersCollaborationsAddCommand.description =\n\t'Create a collaboration for a folder';\nFoldersCollaborationsAddCommand.examples = [\n\t'box folders:collaborations:add 22222 --role editor --user-id 33333',\n];\n\nFoldersCollaborationsAddCommand.flags = {\n\t...CollaborationsCreateCommand.flags,\n};\n\nFoldersCollaborationsAddCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to add a collaboration to',\n\t}),\n};\n\nmodule.exports = FoldersCollaborationsAddCommand;\n"
  },
  {
    "path": "src/commands/folders/collaborations/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Args } = require('@oclif/core');\n\nclass FoldersCollaborationsListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tFoldersCollaborationsListCommand\n\t\t);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet collaborations = await this.client.folders.getCollaborations(\n\t\t\targs.id,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(collaborations);\n\t}\n}\n\nFoldersCollaborationsListCommand.aliases = ['folders:collaborations:list'];\n\nFoldersCollaborationsListCommand.description =\n\t'List all collaborations on a folder';\nFoldersCollaborationsListCommand.examples = [\n\t'box folders:collaborations 22222',\n];\nFoldersCollaborationsListCommand._endpoint = 'get_folders_id_collaborations';\n\nFoldersCollaborationsListCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nFoldersCollaborationsListCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to get the collaborations on',\n\t}),\n};\n\nmodule.exports = FoldersCollaborationsListCommand;\n"
  },
  {
    "path": "src/commands/folders/copy.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass FoldersCopyCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FoldersCopyCommand);\n\t\tlet options = {};\n\n\t\tif (flags.name) {\n\t\t\toptions.name = flags.name;\n\t\t}\n\n\t\tlet folderCopy = await this.client.folders.copy(\n\t\t\targs.id,\n\t\t\targs.parentID,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(folderCopy);\n\t}\n}\n\nFoldersCopyCommand.description = 'Copy a folder to a different folder';\nFoldersCopyCommand.examples = ['box folders:copy 22222 44444'];\nFoldersCopyCommand._endpoint = 'post_folders_id_copy';\n\nFoldersCopyCommand.flags = {\n\t...BoxCommand.flags,\n\tname: Flags.string({ description: 'An optional new name for the folder' }),\n\t'id-only': Flags.boolean({\n\t\tdescription: 'Return only an ID to output from this command',\n\t}),\n};\n\nFoldersCopyCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to copy',\n\t}),\n\tparentID: Args.string({\n\t\tname: 'parentID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the new parent folder to copy the folder into',\n\t}),\n};\n\nmodule.exports = FoldersCopyCommand;\n"
  },
  {
    "path": "src/commands/folders/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass FoldersCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FoldersCreateCommand);\n\t\tlet parameters = {\n\t\t\tbody: {\n\t\t\t\tname: args.name,\n\t\t\t\tparent: {\n\t\t\t\t\tid: args.parentID,\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\n\t\tif (flags.description) {\n\t\t\tparameters.body.description = flags.description;\n\t\t}\n\n\t\t// @TODO (2018-07-10): Should implement this using the Node SDK\n\t\tlet createdFolder = await this.client.wrapWithDefaultHandler(\n\t\t\tthis.client.post\n\t\t)('/folders', parameters);\n\t\tawait this.output(createdFolder);\n\t}\n}\n\nFoldersCreateCommand.description = 'Create a new folder';\nFoldersCreateCommand.examples = ['box folders:create 22222 \"New Subfolder\"'];\nFoldersCreateCommand._endpoint = 'post_folders';\n\nFoldersCreateCommand.flags = {\n\t...BoxCommand.flags,\n\t'id-only': Flags.boolean({\n\t\tdescription: 'Return only an ID to output from this command',\n\t}),\n};\n\nFoldersCreateCommand.args = {\n\tparentID: Args.string({\n\t\tname: 'parentID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription:\n\t\t\t\"ID of parent folder to add new folder to, use '0' for the root folder\",\n\t}),\n\tname: Args.string({\n\t\tname: 'name',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Name of new folder',\n\t}),\n};\n\nmodule.exports = FoldersCreateCommand;\n"
  },
  {
    "path": "src/commands/folders/delete.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst BoxCLIError = require('../../cli-error');\n\nclass FoldersDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FoldersDeleteCommand);\n\t\tif (args.id === '0') {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t\"Cannot delete folder '0': this is the root (All Files) folder and cannot be deleted.\"\n\t\t\t);\n\t\t}\n\t\tlet options = {};\n\n\t\tif (Object.hasOwn(flags, 'recursive')) {\n\t\t\toptions.recursive = flags.recursive;\n\t\t}\n\n\t\tif (flags.etag) {\n\t\t\toptions.etag = flags.etag;\n\t\t}\n\n\t\tawait this.client.folders.delete(args.id, options);\n\n\t\tif (flags.force) {\n\t\t\ttry {\n\t\t\t\tawait this.client.folders.deletePermanently(args.id);\n\t\t\t} catch (error) {\n\t\t\t\t// If the item can't be found in the trash, assume that it was already deleted or\n\t\t\t\t// that the enterprise didn't have trash enabled.  This should be regarded as a success case.\n\t\t\t\tif (error.statusCode !== 404) {\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tthis.info(\n\t\t\t`Deleted folder ${args.id}${flags.force ? ' permanently' : ''}`\n\t\t);\n\t}\n}\n\nFoldersDeleteCommand.description = 'Delete a folder';\nFoldersDeleteCommand.examples = ['box folders:delete 22222'];\nFoldersDeleteCommand._endpoint = 'delete_folders_id';\n\nFoldersDeleteCommand.flags = {\n\t...BoxCommand.flags,\n\tetag: Flags.string({ description: 'Only delete if etag value matches' }),\n\trecursive: Flags.boolean({\n\t\tchar: 'r',\n\t\tdescription: 'Delete the folder, even if it still has items in it',\n\t}),\n\tforce: Flags.boolean({\n\t\tchar: 'f',\n\t\tdescription: 'Permanently delete the folder, bypassing the trash',\n\t}),\n};\n\nFoldersDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to delete',\n\t}),\n};\n\nmodule.exports = FoldersDeleteCommand;\n"
  },
  {
    "path": "src/commands/folders/download.js",
    "content": "'use strict';\n\nconst { Flags, Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\nconst fs = require('node:fs');\nconst { mkdirp } = require('mkdirp');\nconst path = require('node:path');\nconst BoxCLIError = require('../../cli-error');\nconst ora = require('ora');\nconst archiver = require('archiver');\nconst dateTime = require('date-fns');\nconst utilities = require('../../util');\n\n/**\n * Saves a file to disk\n *\n * @param {string} folderPath The folder path this item occurs at within the folder being downloaded\n * @param {Object} file The file record\n * @param {Readable} stream The stream of file contents\n * @returns {Promise<void>} A promise resolving when the file is completely written to disk\n * @throws BoxCLIError\n * @private\n */\nfunction saveFileToDisk(folderPath, file, stream) {\n\tlet output;\n\ttry {\n\t\toutput = fs.createWriteStream(path.join(folderPath, file.path));\n\t\tstream.pipe(output);\n\t} catch (error) {\n\t\tthrow new BoxCLIError(\n\t\t\t`Error downloading file ${file.id} to ${file.path}`,\n\t\t\terror\n\t\t);\n\t}\n\n\t// We need to await the end of the stream to avoid a race condition here\n\treturn new Promise((resolve, reject) => {\n\t\toutput.on('close', resolve);\n\t\tstream.on('error', reject);\n\t});\n}\n\nclass FoldersDownloadCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FoldersDownloadCommand);\n\n\t\tthis.outputPath = null;\n\t\tthis.maxDepth =\n\t\t\tObject.hasOwn(flags, 'depth') && flags.depth >= 0\n\t\t\t\t? flags.depth\n\t\t\t\t: Number.POSITIVE_INFINITY;\n\t\tthis.overwrite = flags.overwrite;\n\n\t\tlet id = args.id;\n\t\tlet outputFinalized = Promise.resolve();\n\t\tlet rootItemPath = null;\n\n\t\tlet destinationPath;\n\t\tif (flags.destination) {\n\t\t\tawait utilities.checkDir(flags.destination, flags['create-path']);\n\t\t\tdestinationPath = flags.destination;\n\t\t} else {\n\t\t\tdestinationPath = this.settings.boxDownloadsFolderPath;\n\t\t}\n\n\t\tif (!fs.existsSync(destinationPath)) {\n\t\t\tthrow new BoxCLIError('Destination path must exist');\n\t\t}\n\n\t\tconst fsStat = fs.statSync(destinationPath);\n\t\tif (!fsStat.isDirectory()) {\n\t\t\tthrow new BoxCLIError('Destination path must be a directory');\n\t\t}\n\n\t\tthis.spinner = ora('Starting download').start();\n\n\t\tif (flags.zip) {\n\t\t\tthis.overwrite = true;\n\t\t\tlet fileName = `folders-download-${id}-${dateTime.format(\n\t\t\t\tnew Date(),\n\t\t\t\t'YYYY-MM-DDTHH_mm_ss_SSS'\n\t\t\t)}.zip`;\n\t\t\trootItemPath = fileName;\n\t\t\toutputFinalized = this._setupZip(\n\t\t\t\tpath.join(destinationPath, fileName)\n\t\t\t);\n\t\t}\n\n\t\ttry {\n\t\t\tthis.outputPath = destinationPath;\n\t\t\tfor await (let item of this._getItems(id, '')) {\n\t\t\t\tif (item.type === 'folder' && !this.zip) {\n\t\t\t\t\t// Set output path to the top-level folder, which is the first item in the generator\n\t\t\t\t\trootItemPath = rootItemPath || item.path;\n\n\t\t\t\t\tthis.spinnerLog(\n\t\t\t\t\t\t`Creating folder ${item.id} at ${item.path}`\n\t\t\t\t\t);\n\t\t\t\t\ttry {\n\t\t\t\t\t\tawait mkdirp(path.join(destinationPath, item.path));\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t\t`Folder ${item.path} could not be created`,\n\t\t\t\t\t\t\terror\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t} else if (item.type === 'file') {\n\t\t\t\t\tthis.spinnerLog(\n\t\t\t\t\t\t`Downloading file ${item.id} to ${item.path}`\n\t\t\t\t\t);\n\t\t\t\t\tlet stream = await this.client.files.getReadStream(item.id);\n\n\t\t\t\t\tif (this.zip) {\n\t\t\t\t\t\tthis.zip.append(stream, { name: item.path });\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// @TODO(2018-08-15): Improve performance by queueing async work and performing in parallel\n\t\t\t\t\t\tawait saveFileToDisk(destinationPath, item, stream);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tthis.spinner.stop();\n\t\t\tthrow error;\n\t\t}\n\n\t\tif (this.zip) {\n\t\t\tthis.zip.finalize();\n\t\t}\n\t\tawait outputFinalized;\n\t\tthis.spinner.succeed(\n\t\t\t`${this.bufferLog || ''}\\nDownloaded folder ${id} to ${path.join(\n\t\t\t\tthis.outputPath,\n\t\t\t\trootItemPath\n\t\t\t)}`.trim()\n\t\t);\n\t}\n\n\tspinnerLog(message, preserveText = false) {\n\t\tthis.spinner.text = `${this.bufferLog || ''}\\n${message}`.trim();\n\t\tif (preserveText) {\n\t\t\tthis.bufferLog = this.spinner.text;\n\t\t}\n\t}\n\n\t/**\n\t * Generator for items in the given folder.  Yields items starting with the top-level folder itself.\n\t * @param {string} folderId The ID of the folder to generate items for\n\t * @param {string} folderPath The relative path so far down the folder tree\n\t * @yields {Object} Item records\n\t * @returns {void}\n\t * @private\n\t */\n\tasync *_getItems(folderId, folderPath) {\n\t\tlet folder = await this.client.folders.get(folderId);\n\t\tfolderPath = path.join(folderPath, folder.name);\n\n\t\tyield {\n\t\t\ttype: 'folder',\n\t\t\tid: folderId,\n\t\t\tname: folder.name,\n\t\t\tpath: folderPath,\n\t\t};\n\n\t\tlet folderItems = folder.item_collection.entries;\n\t\tif (folder.item_collection.total_count > folderItems.length) {\n\t\t\tlet iterator = await this.client.folders.getItems(folderId, {\n\t\t\t\tusemarker: true,\n\t\t\t\tfields: 'type,id,name',\n\t\t\t});\n\t\t\tfolderItems = { [Symbol.asyncIterator]: () => iterator };\n\t\t}\n\t\tfor await (let item of folderItems) {\n\t\t\tif (item.type === 'folder') {\n\t\t\t\t// We only recurse this folder by one of the following conditions:\n\t\t\t\t// 1. The overwrite flag is true. We will download all files and folders within the provided depth (overwite).\n\t\t\t\t// 2. The folder does not exist. We will download all files and folders within the provided depth.\n\t\t\t\t// 3. The folder exists and overwrite is false, we only download files and folders not existing, within the provided depth.\n\n\t\t\t\tif (folderPath.split(path.sep).length <= this.maxDepth) {\n\t\t\t\t\tyield* this._getItems(item.id, folderPath);\n\t\t\t\t} else {\n\t\t\t\t\t// If the folder exists and overwrite is false, we skip the folder.\n\t\t\t\t\tthis.spinnerLog(\n\t\t\t\t\t\t`Skipping folder ${item.name} (${item.id}) at ${folderPath} because reached max depth of ${this.maxDepth}`,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} else if (item.type === 'file') {\n\t\t\t\t// We only download file if overwrite is true or the file does not exist.\n\t\t\t\t// Skip downloading if overwrite is false and the file exists.\n\n\t\t\t\tif (\n\t\t\t\t\tthis.overwrite ||\n\t\t\t\t\t!fs.existsSync(\n\t\t\t\t\t\tpath.join(this.outputPath, folderPath, item.name)\n\t\t\t\t\t)\n\t\t\t\t) {\n\t\t\t\t\tyield {\n\t\t\t\t\t\ttype: 'file',\n\t\t\t\t\t\tid: item.id,\n\t\t\t\t\t\tname: item.name,\n\t\t\t\t\t\tpath: path.join(folderPath, item.name),\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\tthis.spinnerLog(\n\t\t\t\t\t\t`Skipping file ${item.name} (${item.id}) at ${folderPath} because it already exists and overwrite is disabled`,\n\t\t\t\t\t\ttrue\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Sets up a zip archive writing to the given destination.\n\t *\n\t * @param {string} destinationPath The path where the .zip file should be written\n\t * @returns {Promise<void>} A promise resolving when the archive is finalized and written to disk\n\t * @throws BoxCLIError\n\t * @private\n\t */\n\t_setupZip(destinationPath) {\n\t\t// Set up archive stream\n\t\tthis.zip = archiver('zip', {\n\t\t\tzlib: { level: 9 }, // Use the best available compression\n\t\t});\n\n\t\tlet output;\n\t\ttry {\n\t\t\toutput = fs.createWriteStream(destinationPath);\n\t\t} catch (error) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t`Could not write to destination path ${destinationPath}`,\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\n\t\tthis.zip.on('error', (error) => {\n\t\t\tthrow new BoxCLIError('Error writing to zip file', error);\n\t\t});\n\n\t\tthis.zip.pipe(output);\n\n\t\t// We need to await the end of the stream to avoid a race condition here\n\t\treturn new Promise((resolve, reject) => {\n\t\t\toutput.on('close', resolve);\n\t\t\toutput.on('error', reject);\n\t\t});\n\t}\n}\n\nFoldersDownloadCommand.description = 'Download a folder';\nFoldersDownloadCommand.examples = ['box folders:download 22222'];\n\nFoldersDownloadCommand.flags = {\n\t...BoxCommand.flags,\n\tdestination: Flags.string({\n\t\tdescription: 'The destination folder to download the Box folder into',\n\t\tparse: utilities.parsePath,\n\t}),\n\tzip: Flags.boolean({\n\t\tdescription: 'Download the folder into a single .zip archive',\n\t}),\n\tdepth: Flags.integer({\n\t\tdescription:\n\t\t\t'Number of levels deep to recurse when downloading the folder tree',\n\t}),\n\t'create-path': Flags.boolean({\n\t\tdescription:\n\t\t\t'Recursively creates a path to a directory if it does not exist',\n\t\tallowNo: true,\n\t\tdefault: true,\n\t}),\n\toverwrite: Flags.boolean({\n\t\tdescription:\n\t\t\t'[default: true] Overwrite the folder if it already exists.',\n\t\tallowNo: true,\n\t\tdefault: true,\n\t}),\n};\n\nFoldersDownloadCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to download',\n\t}),\n};\n\nmodule.exports = FoldersDownloadCommand;\n"
  },
  {
    "path": "src/commands/folders/get.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Args } = require('@oclif/core');\n\nclass FoldersGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FoldersGetCommand);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet folder = await this.client.folders.get(args.id, options);\n\t\tawait this.output(folder);\n\t}\n}\n\nFoldersGetCommand.description = 'Get information about a folder';\nFoldersGetCommand.examples = ['box folders:get 22222'];\nFoldersGetCommand._endpoint = 'get_folders_id';\n\nFoldersGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nFoldersGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of folder to get; use 0 for the root folder',\n\t}),\n};\n\nmodule.exports = FoldersGetCommand;\n"
  },
  {
    "path": "src/commands/folders/items.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass FoldersListItemsCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FoldersListItemsCommand);\n\t\tlet options = PaginationUtilities.forceMarkerPagination(flags);\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tif (flags.direction) {\n\t\t\toptions.direction = flags.direction;\n\t\t}\n\t\tif (flags.sort) {\n\t\t\toptions.sort = flags.sort;\n\t\t}\n\n\t\tlet items = await this.client.folders.getItems(args.id, options);\n\t\tawait this.output(items);\n\t}\n}\n\nFoldersListItemsCommand.aliases = ['folders:list-items'];\n\nFoldersListItemsCommand.description = 'List items in a folder';\nFoldersListItemsCommand.examples = ['box folders:items 22222'];\nFoldersListItemsCommand._endpoint = 'get_folders_id_items';\n\nFoldersListItemsCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n\tdirection: Flags.string({\n\t\tdescription: 'The direction to order returned items',\n\t\toptions: ['ASC', 'DESC'],\n\t}),\n\tsort: Flags.string({\n\t\tdescription: 'The parameter to sort returned items',\n\t\toptions: ['id', 'name', 'date'],\n\t}),\n};\n\nFoldersListItemsCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription:\n\t\t\t'ID of the folder to get the items in, use 0 for the root folder',\n\t}),\n};\n\nmodule.exports = FoldersListItemsCommand;\n"
  },
  {
    "path": "src/commands/folders/locks/create.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass FoldersLocksCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(FoldersLocksCreateCommand);\n\n\t\tlet lock = await this.client.folders.lock(args.id);\n\t\tawait this.output(lock);\n\t}\n}\n\nFoldersLocksCreateCommand.description = 'Create a lock on a folder';\nFoldersLocksCreateCommand.examples = ['box folders:locks:create 22222'];\nFoldersLocksCreateCommand._endpoint = 'post_folder_locks';\n\nFoldersLocksCreateCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nFoldersLocksCreateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to create a lock on',\n\t}),\n};\n\nmodule.exports = FoldersLocksCreateCommand;\n"
  },
  {
    "path": "src/commands/folders/locks/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass FoldersLocksDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(FoldersLocksDeleteCommand);\n\n\t\tawait this.client.folders.deleteLock(args.id);\n\t\tthis.info(`Delete folder lock with ID ${args.id}`);\n\t}\n}\n\nFoldersLocksDeleteCommand.description = 'Delete a lock on a folder';\nFoldersLocksDeleteCommand.examples = ['box folders:locks:delete 22222'];\nFoldersLocksDeleteCommand._endpoint = 'get_folder_locks_id';\n\nFoldersLocksDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nFoldersLocksDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder lock to delete',\n\t}),\n};\n\nmodule.exports = FoldersLocksDeleteCommand;\n"
  },
  {
    "path": "src/commands/folders/locks/index.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass FoldersLocksListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(FoldersLocksListCommand);\n\n\t\tlet locks = await this.client.folders.getLocks(args.id);\n\t\tawait this.output(locks);\n\t}\n}\n\nFoldersLocksListCommand.aliases = ['folders:locks:list'];\n\nFoldersLocksListCommand.description = 'List all locks on a folder';\nFoldersLocksListCommand.examples = ['box folders:locks 22222'];\nFoldersLocksListCommand._endpoint = 'get_folder_locks';\n\nFoldersLocksListCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nFoldersLocksListCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to get the locks on',\n\t}),\n};\n\nmodule.exports = FoldersLocksListCommand;\n"
  },
  {
    "path": "src/commands/folders/metadata/add.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../../util');\n\nclass FoldersCreateMetadataCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FoldersCreateMetadataCommand);\n\n\t\tlet metadataValues = Object.assign({}, ...flags.data);\n\t\tlet templateKey = flags['template-key'];\n\n\t\tlet metadata = await this.client.folders.addMetadata(\n\t\t\targs.id,\n\t\t\tflags.scope,\n\t\t\ttemplateKey,\n\t\t\tmetadataValues\n\t\t);\n\t\tawait this.output(metadata);\n\t}\n}\n\nFoldersCreateMetadataCommand.aliases = ['folders:metadata:create'];\n\nFoldersCreateMetadataCommand.description = 'Add metadata to a folder';\nFoldersCreateMetadataCommand.examples = [\n\t'box folders:metadata:add 22222 --template-key employeeRecord --data \"name=John Doe\" --data department=Sales',\n\t'box folders:metadata:add 22222 --template-key myTemplate --data \"multiselectkey1=[option1A,option1B]\" --data \"multiselectkey2=[option2A]\"',\n];\nFoldersCreateMetadataCommand._endpoint = 'post_folders_id_metadata_id_id';\n\nFoldersCreateMetadataCommand.flags = {\n\t...BoxCommand.flags,\n\tdata: Flags.string({\n\t\tdescription:\n\t\t\t'Metadata key and value, in the form \"key=value\".  Note: For float type, use \"#\" at the beginning of digits: key2=#1234.50',\n\t\trequired: true,\n\t\tmultiple: true,\n\t\tparse: utilities.parseMetadata,\n\t}),\n\tscope: Flags.string({\n\t\tdescription: 'The scope of the metadata template to use',\n\t\tdefault: 'enterprise',\n\t}),\n\t'template-key': Flags.string({\n\t\tdescription: 'The key of the metadata template to use',\n\t\trequired: true,\n\t}),\n};\n\nFoldersCreateMetadataCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to add metadata to',\n\t}),\n};\n\nmodule.exports = FoldersCreateMetadataCommand;\n"
  },
  {
    "path": "src/commands/folders/metadata/get.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass FoldersGetMetadataCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FoldersGetMetadataCommand);\n\n\t\tlet metadata = await this.client.folders.getMetadata(\n\t\t\targs.id,\n\t\t\tflags.scope,\n\t\t\tflags['template-key']\n\t\t);\n\t\tawait this.output(metadata);\n\t}\n}\n\nFoldersGetMetadataCommand.description =\n\t'Get information about a metadata object';\nFoldersGetMetadataCommand.examples = [\n\t'box folders:metadata:get 22222 --template-key employeeRecord',\n];\nFoldersGetMetadataCommand._endpoint = 'get_folders_id_metadata_id_id';\n\nFoldersGetMetadataCommand.flags = {\n\t...BoxCommand.flags,\n\tscope: Flags.string({\n\t\tdescription: 'The scope of the metadata template to retrieve',\n\t\tdefault: 'enterprise',\n\t}),\n\t'template-key': Flags.string({\n\t\tdescription: 'The key of the metadata template to retrieve',\n\t\trequired: true,\n\t}),\n};\n\nFoldersGetMetadataCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to get metadata on',\n\t}),\n};\n\nmodule.exports = FoldersGetMetadataCommand;\n"
  },
  {
    "path": "src/commands/folders/metadata/index.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass FoldersGetAllMetadataCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(FoldersGetAllMetadataCommand);\n\n\t\tlet metadata = await this.client.folders.getAllMetadata(args.id);\n\t\tawait this.output(metadata);\n\t}\n}\n\nFoldersGetAllMetadataCommand.aliases = ['folders:metadata:get-all'];\n\nFoldersGetAllMetadataCommand.description = 'Get all metadata on a folder';\nFoldersGetAllMetadataCommand.examples = ['box folders:metadata 22222'];\nFoldersGetAllMetadataCommand._endpoint = 'get_folders_id_metadata';\n\nFoldersGetAllMetadataCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nFoldersGetAllMetadataCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to get all metadata on',\n\t}),\n};\n\nmodule.exports = FoldersGetAllMetadataCommand;\n"
  },
  {
    "path": "src/commands/folders/metadata/remove.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass FoldersDeleteMetadataCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FoldersDeleteMetadataCommand);\n\n\t\tawait this.client.folders.deleteMetadata(\n\t\t\targs.id,\n\t\t\tflags.scope,\n\t\t\tflags['template-key']\n\t\t);\n\t\tthis.info(`Successfully deleted metadata ${flags['template-key']}`);\n\t}\n}\n\nFoldersDeleteMetadataCommand.aliases = ['folders:metadata:delete'];\n\nFoldersDeleteMetadataCommand.description = 'Delete metadata from a folder';\nFoldersDeleteMetadataCommand.examples = [\n\t'box folders:metadata:remove 22222 --scope global --template-key properties',\n];\nFoldersDeleteMetadataCommand._endpoint = 'delete_folders_id_metadata_id_id';\n\nFoldersDeleteMetadataCommand.flags = {\n\t...BoxCommand.flags,\n\tscope: Flags.string({\n\t\tdescription: 'The scope of the metadata template to remove',\n\t\tdefault: 'enterprise',\n\t}),\n\t'template-key': Flags.string({\n\t\tdescription: 'The key of the metadata template to remove',\n\t\trequired: true,\n\t}),\n};\n\nFoldersDeleteMetadataCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to remove metadata from',\n\t}),\n};\n\nmodule.exports = FoldersDeleteMetadataCommand;\n"
  },
  {
    "path": "src/commands/folders/metadata/set.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../../util');\n\nclass FoldersSetMetadataCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FoldersSetMetadataCommand);\n\n\t\tlet metadataValues = Object.assign({}, ...flags.data);\n\t\tlet templateKey = flags['template-key'];\n\n\t\tlet metadata = await this.client.folders.setMetadata(\n\t\t\targs.id,\n\t\t\tflags.scope,\n\t\t\ttemplateKey,\n\t\t\tmetadataValues\n\t\t);\n\t\tawait this.output(metadata);\n\t}\n}\n\nFoldersSetMetadataCommand.description = 'Set metadata on a folder';\nFoldersSetMetadataCommand.examples = [\n\t'box folders:metadata:set 22222 --template-key employeeRecord --data \"name=John Doe\" --data department=Sales',\n\t'box folders:metadata:set 22222 --template-key myTemplate --data \"multiselectkey1=[option1A,option1B]\" --data \"multiselectkey2=[option2A]\"',\n];\n\nFoldersSetMetadataCommand.flags = {\n\t...BoxCommand.flags,\n\tdata: Flags.string({\n\t\tdescription:\n\t\t\t'Metadata key and value, in the form \"key=value\".  Note: For float type, use \"#\" at the beginning of digits: key2=#1234.50',\n\t\trequired: true,\n\t\tmultiple: true,\n\t\tparse: utilities.parseMetadata,\n\t}),\n\tscope: Flags.string({\n\t\tdescription: 'The scope of the metadata template to use',\n\t\tdefault: 'enterprise',\n\t}),\n\t'template-key': Flags.string({\n\t\tdescription: 'The key of the metadata template to use',\n\t\trequired: true,\n\t}),\n};\n\nFoldersSetMetadataCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to add metadata to',\n\t}),\n};\n\nmodule.exports = FoldersSetMetadataCommand;\n"
  },
  {
    "path": "src/commands/folders/metadata/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../../util');\n\nconst OP_FLAGS = Object.freeze({\n\tadd: true,\n\tcopy: true,\n\tmove: true,\n\tremove: true,\n\treplace: true,\n\ttest: true,\n});\n\nclass FoldersUpdateMetadataCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args, raw } = await this.parse(\n\t\t\tFoldersUpdateMetadataCommand\n\t\t);\n\n\t\tlet updates = raw\n\t\t\t.filter((v) => v.type === 'flag' && OP_FLAGS[v.flag])\n\t\t\t.map((op) => {\n\t\t\t\tlet opName = op.flag;\n\t\t\t\tlet opData = flags[op.flag].shift();\n\n\t\t\t\treturn { op: opName, ...opData };\n\t\t\t});\n\n\t\tlet templateKey = flags['template-key'];\n\n\t\tlet metadata = await this.client.folders.updateMetadata(\n\t\t\targs.id,\n\t\t\tflags.scope,\n\t\t\ttemplateKey,\n\t\t\tupdates\n\t\t);\n\t\tawait this.output(metadata);\n\t}\n}\n\nFoldersUpdateMetadataCommand.description =\n\t'Update the metadata attached to a folder';\nFoldersUpdateMetadataCommand.examples = [\n\t'box folders:metadata:update 22222 --template-key employeeRecord --replace department=Finance',\n];\nFoldersUpdateMetadataCommand._endpoint = 'put_folders_id_metadata_id_id';\n\nFoldersUpdateMetadataCommand.flags = {\n\t...BoxCommand.flags,\n\tscope: Flags.string({\n\t\tdescription: 'The scope of the metadata template to update against',\n\t\tdefault: 'enterprise',\n\t}),\n\t'template-key': Flags.string({\n\t\tdescription: 'The key of the metadata template to update against',\n\t\trequired: true,\n\t}),\n\tadd: Flags.string({\n\t\tchar: 'a',\n\t\tdescription:\n\t\t\t'Add a key to the metadata document; must be in the form key=value',\n\t\tmultiple: true,\n\t\tparse: utilities.parseMetadataOp,\n\t}),\n\tcopy: Flags.string({\n\t\tchar: 'c',\n\t\tdescription:\n\t\t\t'Copy a metadata value to another key; must be in the form sourceKey>destinationKey',\n\t\tmultiple: true,\n\t\tparse: utilities.parseMetadataOp,\n\t}),\n\tmove: Flags.string({\n\t\tchar: 'm',\n\t\tdescription:\n\t\t\t'Move a metadata value from one key to another; must be in the form sourceKey>destinationKey',\n\t\tmultiple: true,\n\t\tparse: utilities.parseMetadataOp,\n\t}),\n\tremove: Flags.string({\n\t\tdescription: 'Remove a key from the metadata document',\n\t\tmultiple: true,\n\t\tparse: utilities.parseMetadataOp,\n\t}),\n\treplace: Flags.string({\n\t\tdescription:\n\t\t\t'Replace the value of an existing metadata key; must be in the form key=value',\n\t\tmultiple: true,\n\t\tparse: utilities.parseMetadataOp,\n\t}),\n\ttest: Flags.string({\n\t\tchar: 'T',\n\t\tdescription:\n\t\t\t'Test that a metadata key contains a specific value; must be in the form key=value',\n\t\tmultiple: true,\n\t\tparse: utilities.parseMetadataOp,\n\t}),\n};\n\nFoldersUpdateMetadataCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to update metadata on',\n\t}),\n};\n\nmodule.exports = FoldersUpdateMetadataCommand;\n"
  },
  {
    "path": "src/commands/folders/move.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass FoldersMoveCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FoldersMoveCommand);\n\t\tlet updates = {\n\t\t\tparent: {\n\t\t\t\tid: args.parentID,\n\t\t\t},\n\t\t};\n\n\t\tif (flags.etag) {\n\t\t\tupdates.etag = flags.etag;\n\t\t}\n\n\t\tif (flags['owned-by']) {\n\t\t\tupdates.owned_by = {\n\t\t\t\tid: flags['owned-by'],\n\t\t\t};\n\t\t}\n\n\t\tlet movedFolder = await this.client.folders.update(args.id, updates);\n\t\tawait this.output(movedFolder);\n\t}\n}\n\nFoldersMoveCommand.description = 'Move a folder to a different folder';\nFoldersMoveCommand.examples = ['box folders:move 22222 44444'];\nFoldersMoveCommand._endpoint = 'put_folders_id move';\n\nFoldersMoveCommand.flags = {\n\t...BoxCommand.flags,\n\tetag: Flags.string({ description: 'Only move if etag value matches' }),\n\t'owned-by': Flags.string({\n\t\tdescription: 'ID of the user to own the folder',\n\t}),\n};\n\nFoldersMoveCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of folder to copy',\n\t}),\n\tparentID: Args.string({\n\t\tname: 'parentID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the new parent folder to move the folder into',\n\t}),\n};\n\nmodule.exports = FoldersMoveCommand;\n"
  },
  {
    "path": "src/commands/folders/rename.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass FoldersRenameCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FoldersRenameCommand);\n\t\tlet updates = {\n\t\t\tname: args.name,\n\t\t};\n\n\t\tif (flags.description) {\n\t\t\tupdates.description = flags.description;\n\t\t}\n\n\t\tif (flags.etag) {\n\t\t\tupdates.etag = flags.etag;\n\t\t}\n\n\t\tlet renamedFolder = await this.client.folders.update(args.id, updates);\n\t\tawait this.output(renamedFolder);\n\t}\n}\n\nFoldersRenameCommand.description = 'Rename a folder';\nFoldersRenameCommand.examples = ['box folders:rename 22222 \"New Folder Name\"'];\n\nFoldersRenameCommand.flags = {\n\t...BoxCommand.flags,\n\tdescription: Flags.string({\n\t\tdescription: 'Change the folder description',\n\t\tparse: utilities.unescapeSlashes,\n\t}),\n\tetag: Flags.string({ description: 'Only rename if etag value matches' }),\n};\n\nFoldersRenameCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to rename',\n\t}),\n\tname: Args.string({\n\t\tname: 'name',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'New name for the folder',\n\t}),\n};\n\nmodule.exports = FoldersRenameCommand;\n"
  },
  {
    "path": "src/commands/folders/share.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Args } = require('@oclif/core');\nconst { sharedLinkFlags } = require('../shared-links/create');\nconst SharedLinksModule = require('../../modules/shared-links');\n\nclass FoldersShareCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args, flags } = await this.parse(FoldersShareCommand);\n\n\t\t// Transform arguments for generic module\n\t\targs.itemType = 'folder';\n\t\targs.itemID = args.id;\n\t\tdelete args.id;\n\n\t\tlet sharedLinksModule = new SharedLinksModule(this.client);\n\t\tlet updatedItem = await sharedLinksModule.createSharedLink(args, flags);\n\t\tawait this.output(updatedItem);\n\t}\n}\n\nFoldersShareCommand.aliases = [\n\t'folders:shared-links:create',\n\t'folders:shared-links:update',\n];\n\nFoldersShareCommand.description = 'Create a shared link for a folder';\nFoldersShareCommand.examples = [\n\t'box folders:share 22222 --access company --vanity-name my-custom-name-123',\n];\nFoldersShareCommand._endpoint = 'put_folders_id create_shared_link';\n\nFoldersShareCommand.flags = {\n\t...sharedLinkFlags,\n};\n\nFoldersShareCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to share',\n\t}),\n};\n\nmodule.exports = FoldersShareCommand;\n"
  },
  {
    "path": "src/commands/folders/unshare.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst SharedLinksDeleteCommand = require('../shared-links/delete');\nconst SharedLinksModule = require('../../modules/shared-links');\nconst chalk = require('chalk');\nconst { Args } = require('@oclif/core');\n\nclass FoldersUnshareCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(FoldersUnshareCommand);\n\n\t\t// Transform arguments for generic module\n\t\targs.itemType = 'folder';\n\t\targs.itemID = args.id;\n\t\tdelete args.id;\n\n\t\tlet sharedLinksModule = new SharedLinksModule(this.client);\n\t\tlet item = await sharedLinksModule.removeSharedLink(args);\n\t\tthis.info(\n\t\t\tchalk`{green Removed shared link from ${args.itemType} \"${item.name}\"}`\n\t\t);\n\t}\n}\n\nFoldersUnshareCommand.aliases = ['folders:shared-links:delete'];\n\nFoldersUnshareCommand.description = 'Delete a shared link for a folder';\nFoldersUnshareCommand.examples = ['box folders:unshare 22222'];\nFoldersUnshareCommand._endpoint = 'put_folders_id delete_shared_link';\n\nFoldersUnshareCommand.flags = {\n\t...SharedLinksDeleteCommand.flags,\n};\n\nFoldersUnshareCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to unshare',\n\t}),\n};\n\nmodule.exports = FoldersUnshareCommand;\n"
  },
  {
    "path": "src/commands/folders/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass FoldersUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FoldersUpdateCommand);\n\t\tlet updates = {};\n\n\t\tif (flags.name) {\n\t\t\tupdates.name = flags.name;\n\t\t}\n\t\tif (Object.hasOwn(flags, 'can-non-owners-invite')) {\n\t\t\tupdates.can_non_owners_invite = flags['can-non-owners-invite'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'can-non-owners-view-collaborators')) {\n\t\t\tupdates.can_non_owners_view_collaborators =\n\t\t\t\tflags['can-non-owners-view-collaborators'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'description')) {\n\t\t\tupdates.description = flags.description;\n\t\t}\n\t\tif (flags['upload-email-access']) {\n\t\t\tupdates.folder_upload_email = {\n\t\t\t\taccess: flags['upload-email-access'],\n\t\t\t};\n\t\t}\n\t\tif (Object.hasOwn(flags, 'restrict-collaboration')) {\n\t\t\tupdates.can_non_owners_invite = !flags['restrict-collaboration'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'restrict-to-enterprise')) {\n\t\t\tupdates.is_collaboration_restricted_to_enterprise =\n\t\t\t\tflags['restrict-to-enterprise'];\n\t\t}\n\t\tif (flags.tags) {\n\t\t\tupdates.tags = flags.tags.split(',');\n\t\t}\n\t\tif (Object.hasOwn(flags, 'sync')) {\n\t\t\tupdates.sync_state = flags.sync ? 'synced' : 'not_synced';\n\t\t}\n\n\t\tif (flags.etag) {\n\t\t\tupdates.etag = flags.etag;\n\t\t}\n\n\t\tlet updatedFolder = await this.client.folders.update(args.id, updates);\n\t\tawait this.output(updatedFolder);\n\t}\n}\n\nFoldersUpdateCommand.description = 'Update a folder';\nFoldersUpdateCommand.examples = [\n\t'box folders:update 22222 --name \"New Folder Name\"',\n];\nFoldersUpdateCommand._endpoint = 'put_folders_id';\n\nFoldersUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\tname: Flags.string({ description: 'New name for folder' }),\n\t'can-non-owners-invite': Flags.boolean({\n\t\tdescription:\n\t\t\t'Specifies if users who are not the owner of the folder can invite new collaborators to the folder.',\n\t\tallowNo: true,\n\t}),\n\t'can-non-owners-view-collaborators': Flags.boolean({\n\t\tdescription:\n\t\t\t'Restricts collaborators who are not the owner of this folder from viewing other collaborations on this folder.',\n\t\tallowNo: true,\n\t}),\n\tdescription: Flags.string({\n\t\tdescription: 'New description for folder',\n\t\tparse: utilities.unescapeSlashes,\n\t}),\n\t'upload-email-access': Flags.string({\n\t\tdescription: 'Upload email access level',\n\t\toptions: ['open', 'collaborators'],\n\t}),\n\ttags: Flags.string({ description: 'Comma seperated tags' }),\n\tsync: Flags.boolean({\n\t\tdescription: 'Whether the folder is synced to desktop',\n\t\tallowNo: true,\n\t}),\n\t'restrict-collaboration': Flags.boolean({\n\t\tdescription:\n\t\t\t'Restrict collaboration so only owners can invite new collaborators',\n\t\tallowNo: true,\n\t}),\n\t'restrict-to-enterprise': Flags.boolean({\n\t\tdescription:\n\t\t\t\"Restrict collaboration so only users in the folder owner's enterprise can be added\",\n\t\tallowNo: true,\n\t}),\n\tetag: Flags.string({\n\t\tdescription: 'Only apply updates if the etag value matches',\n\t}),\n};\n\nFoldersUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the folder to update',\n\t}),\n};\n\nmodule.exports = FoldersUpdateCommand;\n"
  },
  {
    "path": "src/commands/folders/upload.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst fs = require('node:fs');\nconst path = require('node:path');\nconst BoxCLIError = require('../../cli-error');\nconst utilities = require('../../util');\nconst { CHUNKED_UPLOAD_FILE_SIZE } = require('../../modules/upload');\n\nclass FoldersUploadCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(FoldersUploadCommand);\n\n\t\tlet folderId = await this.uploadFolder(\n\t\t\targs.path,\n\t\t\tflags['parent-folder'],\n\t\t\tflags['folder-name']\n\t\t);\n\t\tlet folder = await this.client.folders.get(folderId);\n\t\tawait this.output(folder);\n\t}\n\n\tasync uploadFolder(folderPath, parentFolderId, folderName) {\n\t\tfolderName = folderName || path.basename(folderPath);\n\n\t\tlet folderItems;\n\t\ttry {\n\t\t\tfolderItems = await utilities.readdirAsync(folderPath);\n\t\t} catch (error) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t`Could not read directory ${folderPath}`,\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\t\t// Filters out files or folders that have a \".\" as the first character in their name. These won't be uploaded.\n\t\tfolderItems = folderItems.filter((item) => item[0] !== '.');\n\n\t\tlet folder = await this.client.folders.create(\n\t\t\tparentFolderId,\n\t\t\tfolderName\n\t\t);\n\t\tlet folderId = folder.id;\n\n\t\t// @TODO(2018-09-14): Add --preserve-timestamps flag\n\n\t\tfor (let item of folderItems) {\n\t\t\t// @TODO(2018-08-15): Improve performance by queueing async work and performing it in parallel\n\n\t\t\tlet itemPath = path.join(folderPath, item);\n\t\t\tlet itemStat = fs.statSync(itemPath);\n\t\t\tif (itemStat.isDirectory()) {\n\t\t\t\tawait this.uploadFolder(itemPath, folderId);\n\t\t\t} else {\n\t\t\t\tlet size = itemStat.size;\n\n\t\t\t\ttry {\n\t\t\t\t\tlet fileStream = fs.createReadStream(itemPath);\n\t\t\t\t\tif (size < CHUNKED_UPLOAD_FILE_SIZE) {\n\t\t\t\t\t\tawait this.client.files.uploadFile(\n\t\t\t\t\t\t\tfolderId,\n\t\t\t\t\t\t\titem,\n\t\t\t\t\t\t\tfileStream\n\t\t\t\t\t\t);\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlet uploader =\n\t\t\t\t\t\t\tawait this.client.files.getChunkedUploader(\n\t\t\t\t\t\t\t\tfolderId,\n\t\t\t\t\t\t\t\tsize,\n\t\t\t\t\t\t\t\titem,\n\t\t\t\t\t\t\t\tfileStream\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\tawait uploader.start();\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t`Could not upload file ${itemPath}`,\n\t\t\t\t\t\terror\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn folderId;\n\t}\n}\n\nFoldersUploadCommand.description = 'Upload a folder';\nFoldersUploadCommand.examples = ['box folders:upload /path/to/folder'];\n\nFoldersUploadCommand.flags = {\n\t...BoxCommand.flags,\n\t'folder-name': Flags.string({\n\t\tdescription: 'Name to use for folder if not using local folder name',\n\t}),\n\t'id-only': Flags.boolean({\n\t\tdescription: 'Return only an ID to output from this command',\n\t}),\n\t'parent-folder': Flags.string({\n\t\tchar: 'p',\n\t\tdescription:\n\t\t\t'Folder to upload this folder into; defaults to the root folder',\n\t\tdefault: '0',\n\t}),\n};\n\nFoldersUploadCommand.args = {\n\tpath: Args.string({\n\t\tname: 'path',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Local path to the folder to upload',\n\t}),\n};\n\nmodule.exports = FoldersUploadCommand;\n"
  },
  {
    "path": "src/commands/groups/collaborations.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass GroupsListCollaborationsCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tGroupsListCollaborationsCommand\n\t\t);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet collaborations = await this.client.groups.getCollaborations(\n\t\t\targs.id,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(collaborations);\n\t}\n}\n\nGroupsListCollaborationsCommand.aliases = [\n\t'groups:list-collaborations',\n\t'collaborations:list-for-group',\n];\n\nGroupsListCollaborationsCommand.description = 'List collaborations for a group';\nGroupsListCollaborationsCommand.examples = ['box groups:collaborations 12345'];\nGroupsListCollaborationsCommand._endpoint = 'get_groups_id_collaborations';\n\nGroupsListCollaborationsCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flag,\n};\n\nGroupsListCollaborationsCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the group to get collaborations for',\n\t}),\n};\n\nmodule.exports = GroupsListCollaborationsCommand;\n"
  },
  {
    "path": "src/commands/groups/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass GroupsCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(GroupsCreateCommand);\n\t\tlet options = {};\n\n\t\tif (flags.description) {\n\t\t\toptions.description = flags.description;\n\t\t}\n\t\tif (flags['external-sync-identifier']) {\n\t\t\toptions.external_sync_identifier =\n\t\t\t\tflags['external-sync-identifier'];\n\t\t}\n\t\tif (flags.provenance) {\n\t\t\toptions.provenance = flags.provenance;\n\t\t}\n\t\tif (flags.invite) {\n\t\t\toptions.invitability_level = flags.invite;\n\t\t}\n\t\tif (flags['view-members']) {\n\t\t\toptions.member_viewability_level = flags['view-members'];\n\t\t}\n\n\t\tlet group = await this.client.groups.create(args.name, options);\n\t\tawait this.output(group);\n\t}\n}\n\nGroupsCreateCommand.description = 'Create a group';\nGroupsCreateCommand.examples = ['box groups:create \"US Employees\"'];\nGroupsCreateCommand._endpoint = 'post_groups';\n\nGroupsCreateCommand.flags = {\n\t...BoxCommand.flags,\n\tdescription: Flags.string({\n\t\tdescription: 'Description of the group',\n\t\tparse: utilities.unescapeSlashes,\n\t}),\n\t'external-sync-identifier': Flags.string({\n\t\tdescription:\n\t\t\t'Group identifier for groups coming from an external source',\n\t}),\n\tprovenance: Flags.string({\n\t\tdescription: 'Track the external source where the group is coming from',\n\t}),\n\tinvite: Flags.string({\n\t\tchar: 'i',\n\t\tdescription: 'Specifies who can invite the group to collaborate',\n\t\toptions: ['admins_only', 'admins_and_members', 'all_managed_users'],\n\t}),\n\t'view-members': Flags.string({\n\t\tchar: 'm',\n\t\tdescription: 'Specifies who can view the members of the group',\n\t\toptions: ['admins_only', 'admins_and_members', 'all_managed_users'],\n\t}),\n\t'id-only': Flags.boolean({\n\t\tdescription: 'Return only an ID to output from this command',\n\t}),\n};\n\nGroupsCreateCommand.args = {\n\tname: Args.string({\n\t\tname: 'name',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Group name',\n\t}),\n};\n\nmodule.exports = GroupsCreateCommand;\n"
  },
  {
    "path": "src/commands/groups/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass GroupsDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(GroupsDeleteCommand);\n\n\t\tawait this.client.groups.delete(args.id);\n\t\tthis.info(`Deleted group ${args.id}`);\n\t}\n}\n\nGroupsDeleteCommand.description = 'Delete a group';\nGroupsDeleteCommand.examples = ['box groups:delete 12345'];\nGroupsDeleteCommand._endpoint = 'delete_groups_id';\n\nGroupsDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nGroupsDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the group to delete',\n\t}),\n};\n\nmodule.exports = GroupsDeleteCommand;\n"
  },
  {
    "path": "src/commands/groups/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass GroupsGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(GroupsGetCommand);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet group = await this.client.groups.get(args.id, options);\n\t\tawait this.output(group);\n\t}\n}\n\nGroupsGetCommand.description = 'Get information about a group';\nGroupsGetCommand.examples = ['box groups:get 12345'];\nGroupsGetCommand._endpoint = 'get_groups_id';\n\nGroupsGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nGroupsGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the group to get',\n\t}),\n};\n\nmodule.exports = GroupsGetCommand;\n"
  },
  {
    "path": "src/commands/groups/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass GroupsListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(GroupsListCommand);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tif (flags.filter) {\n\t\t\toptions.filter_term = flags.filter;\n\t\t}\n\n\t\tlet groups = await this.client.groups.getAll(options);\n\t\tawait this.output(groups);\n\t}\n}\n\nGroupsListCommand.aliases = ['groups:list'];\n\nGroupsListCommand.description = 'List all groups';\nGroupsListCommand.examples = ['box groups'];\nGroupsListCommand._endpoint = 'get_groups';\n\nGroupsListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n\tfilter: Flags.string({\n\t\tdescription:\n\t\t\t'Search term to filter groups on; matches prefixes of group name',\n\t}),\n};\n\nmodule.exports = GroupsListCommand;\n"
  },
  {
    "path": "src/commands/groups/memberships/add.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass GroupsAddMembershipCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(GroupsAddMembershipCommand);\n\t\tlet options = { configurable_permissions: {} };\n\n\t\tif (Object.hasOwn(flags, 'can-run-reports')) {\n\t\t\toptions.configurable_permissions.can_run_reports =\n\t\t\t\tflags['can-run-reports'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'can-instant-login')) {\n\t\t\toptions.configurable_permissions.can_instant_login =\n\t\t\t\tflags['can-instant-login'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'can-create-accounts')) {\n\t\t\toptions.configurable_permissions.can_create_accounts =\n\t\t\t\tflags['can-create-accounts'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'can-edit-accounts')) {\n\t\t\toptions.configurable_permissions.can_edit_accounts =\n\t\t\t\tflags['can-edit-accounts'];\n\t\t}\n\n\t\t// Set role from the \"role\" flag first, since it has a default value\n\t\toptions.role = flags.role;\n\n\t\tif (flags['set-admin']) {\n\t\t\toptions.role = this.client.groups.userRoles.ADMIN;\n\t\t} else if (flags['set-member']) {\n\t\t\toptions.role = this.client.groups.userRoles.MEMBER;\n\t\t}\n\n\t\tlet membership = await this.client.groups.addUser(\n\t\t\targs.groupID,\n\t\t\targs.userID,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(membership);\n\t}\n}\n\nGroupsAddMembershipCommand.aliases = ['groups:membership:add'];\n\nGroupsAddMembershipCommand.description = 'Add a user to a group';\nGroupsAddMembershipCommand.examples = [\n\t'box groups:memberships:add 33333 12345',\n];\nGroupsAddMembershipCommand._endpoint = 'post_group_memberships';\n\nGroupsAddMembershipCommand.flags = {\n\t...BoxCommand.flags,\n\trole: Flags.string({\n\t\tchar: 'r',\n\t\tdescription: \"Set the user's role in the group\",\n\t\tdefault: 'member',\n\t\toptions: ['member', 'admin'],\n\t}),\n\t'set-admin': Flags.boolean({\n\t\tdescription: \"Set the user's role to Group Admin\",\n\t\texclusive: ['set-member'],\n\t\thidden: true,\n\t}),\n\t'set-member': Flags.boolean({\n\t\tdescription: \"Set the user's role to Group Member\",\n\t\texclusive: ['set-admin'],\n\t\thidden: true,\n\t}),\n\t'can-run-reports': Flags.boolean({\n\t\tdescription: 'If the user is a group admin, allow them to run reports',\n\t\tallowNo: true,\n\t}),\n\t'can-instant-login': Flags.boolean({\n\t\tdescription:\n\t\t\t'If the user is a group admin, allow them to instant login',\n\t\tallowNo: true,\n\t}),\n\t'can-create-accounts': Flags.boolean({\n\t\tdescription:\n\t\t\t'If the user is a group admin, allow them to create new users',\n\t\tallowNo: true,\n\t}),\n\t'can-edit-accounts': Flags.boolean({\n\t\tdescription:\n\t\t\t'If the user is a group admin, allow them to edit user accounts',\n\t\tallowNo: true,\n\t}),\n};\n\nGroupsAddMembershipCommand.args = {\n\tuserID: Args.string({\n\t\tname: 'userID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the user to add to the group',\n\t}),\n\tgroupID: Args.string({\n\t\tname: 'groupID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the group to add the user to',\n\t}),\n};\n\nmodule.exports = GroupsAddMembershipCommand;\n"
  },
  {
    "path": "src/commands/groups/memberships/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass GroupsGetMembershipCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(GroupsGetMembershipCommand);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet membership = await this.client.groups.getMembership(\n\t\t\targs.id,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(membership);\n\t}\n}\n\nGroupsGetMembershipCommand.aliases = ['groups:membership:get'];\n\nGroupsGetMembershipCommand.description =\n\t'Get information about a group membership';\nGroupsGetMembershipCommand.examples = ['box groups:memberships:get 12345'];\nGroupsGetMembershipCommand._endpoint = 'get_group_memberships_id';\n\nGroupsGetMembershipCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nGroupsGetMembershipCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the group membership to get',\n\t}),\n};\n\nmodule.exports = GroupsGetMembershipCommand;\n"
  },
  {
    "path": "src/commands/groups/memberships/index.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\nconst PaginationUtilities = require('../../../pagination-utils');\n\nclass GroupsListMembershipCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(GroupsListMembershipCommand);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet members = await this.client.groups.getMemberships(args.id, options);\n\t\tawait this.output(members);\n\t}\n}\n\nGroupsListMembershipCommand.aliases = ['groups:membership:list'];\n\nGroupsListMembershipCommand.description = 'List members of a group';\nGroupsListMembershipCommand.examples = ['box groups:memberships 12345'];\nGroupsListMembershipCommand._endpoint = 'get_groups_id_memberships';\n\nGroupsListMembershipCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nGroupsListMembershipCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the group to get memberships for',\n\t}),\n};\n\nmodule.exports = GroupsListMembershipCommand;\n"
  },
  {
    "path": "src/commands/groups/memberships/remove.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass GroupsRemoveMembershipCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(GroupsRemoveMembershipCommand);\n\n\t\tawait this.client.groups.removeMembership(args.id);\n\t\tthis.info(`Removed membership ${args.id}`);\n\t}\n}\n\nGroupsRemoveMembershipCommand.aliases = ['groups:membership:remove'];\n\nGroupsRemoveMembershipCommand.description = 'Remove a user from a group';\nGroupsRemoveMembershipCommand.examples = [\n\t'box groups:memberships:remove 12345',\n];\nGroupsRemoveMembershipCommand._endpoint = 'delete_group_memberships_id';\n\nGroupsRemoveMembershipCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nGroupsRemoveMembershipCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the group membership record to delete',\n\t}),\n};\n\nmodule.exports = GroupsRemoveMembershipCommand;\n"
  },
  {
    "path": "src/commands/groups/memberships/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass GroupsUpdateMembershipCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(GroupsUpdateMembershipCommand);\n\t\tlet options = { configurable_permissions: {} };\n\n\t\tif (Object.hasOwn(flags, 'can-run-reports')) {\n\t\t\toptions.configurable_permissions.can_run_reports =\n\t\t\t\tflags['can-run-reports'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'can-instant-login')) {\n\t\t\toptions.configurable_permissions.can_instant_login =\n\t\t\t\tflags['can-instant-login'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'can-create-accounts')) {\n\t\t\toptions.configurable_permissions.can_create_accounts =\n\t\t\t\tflags['can-create-accounts'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'can-edit-accounts')) {\n\t\t\toptions.configurable_permissions.can_edit_accounts =\n\t\t\t\tflags['can-edit-accounts'];\n\t\t}\n\t\tif (flags['set-admin']) {\n\t\t\toptions.role = this.client.groups.userRoles.ADMIN;\n\t\t} else if (flags['set-member']) {\n\t\t\toptions.role = this.client.groups.userRoles.MEMBER;\n\t\t}\n\t\tif (flags.role) {\n\t\t\toptions.role = flags.role;\n\t\t}\n\n\t\tlet membership = await this.client.groups.updateMembership(\n\t\t\targs.id,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(membership);\n\t}\n}\n\nGroupsUpdateMembershipCommand.aliases = ['groups:membership:update'];\n\nGroupsUpdateMembershipCommand.description =\n\t\"Update a user's membership to a group\";\nGroupsUpdateMembershipCommand.examples = ['box groups:memberships:update'];\nGroupsUpdateMembershipCommand._endpoint = 'put_group_memberships_id';\n\nGroupsUpdateMembershipCommand.flags = {\n\t...BoxCommand.flags,\n\trole: Flags.string({\n\t\tchar: 'r',\n\t\tdescription: \"Set the user's role in the group\",\n\t\toptions: ['member', 'admin'],\n\t\texclusive: ['set-admin', 'set-member'],\n\t}),\n\t'set-admin': Flags.boolean({\n\t\tdescription: \"Set the user's role to Group Admin\",\n\t\texclusive: ['set-member', 'role'],\n\t\thidden: true,\n\t}),\n\t'set-member': Flags.boolean({\n\t\tdescription: \"Set the user's role to Group Member\",\n\t\texclusive: ['set-admin', 'role'],\n\t\thidden: true,\n\t}),\n\t'can-run-reports': Flags.boolean({\n\t\tdescription: 'If the user is a group admin, allow them to run reports',\n\t\tallowNo: true,\n\t}),\n\t'can-instant-login': Flags.boolean({\n\t\tdescription:\n\t\t\t'If the user is a group admin, allow them to instant login',\n\t\tallowNo: true,\n\t}),\n\t'can-create-accounts': Flags.boolean({\n\t\tdescription:\n\t\t\t'If the user is a group admin, allow them to create new users',\n\t\tallowNo: true,\n\t}),\n\t'can-edit-accounts': Flags.boolean({\n\t\tdescription:\n\t\t\t'If the user is a group admin, allow them to edit user accounts',\n\t\tallowNo: true,\n\t}),\n};\n\nGroupsUpdateMembershipCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the group membership to update',\n\t}),\n};\n\nmodule.exports = GroupsUpdateMembershipCommand;\n"
  },
  {
    "path": "src/commands/groups/terminate-session.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\n\nclass GroupsTerminateSessionCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(GroupsTerminateSessionCommand);\n\n\t\tlet response = await this.client.groups.terminateSession(\n\t\t\tflags['group-ids']\n\t\t);\n\t\tawait this.output(response);\n\t}\n}\n\nGroupsTerminateSessionCommand.description =\n\t\"Validates the roles and permissions of the group, and creates asynchronous jobs to terminate the group's sessions.\";\nGroupsTerminateSessionCommand.examples = [\n\t'box groups:terminate-session --group-ids 123 345',\n];\nGroupsTerminateSessionCommand._endpoint = 'post_groups_terminate_sessions';\n\nGroupsTerminateSessionCommand.flags = {\n\t...BoxCommand.flags,\n\t'group-ids': Flags.string({\n\t\tdescription: 'A list of group IDs',\n\t\tmultiple: true,\n\t\trequired: true,\n\t}),\n};\n\nmodule.exports = GroupsTerminateSessionCommand;\n"
  },
  {
    "path": "src/commands/groups/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass GroupsUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(GroupsUpdateCommand);\n\t\tlet updates = {};\n\n\t\tif (flags.name) {\n\t\t\tupdates.name = flags.name;\n\t\t}\n\t\tif (flags.description) {\n\t\t\tupdates.description = flags.description;\n\t\t}\n\t\tif (flags['external-sync-identifier']) {\n\t\t\tupdates.external_sync_identifier =\n\t\t\t\tflags['external-sync-identifier'];\n\t\t}\n\t\tif (flags.provenance) {\n\t\t\tupdates.provenance = flags.provenance;\n\t\t}\n\t\tif (flags.invite) {\n\t\t\tupdates.invitability_level = flags.invite;\n\t\t}\n\t\tif (flags['view-members']) {\n\t\t\tupdates.member_viewability_level = flags['view-members'];\n\t\t}\n\n\t\tlet group = await this.client.groups.update(args.id, updates);\n\t\tawait this.output(group);\n\t}\n}\n\nGroupsUpdateCommand.description = 'Update a group';\nGroupsUpdateCommand.examples = [\n\t'box groups:update 12345 --name \"U.S. Employees\"',\n];\nGroupsUpdateCommand._endpoint = 'put_groups_id';\n\nGroupsUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\tname: Flags.string({\n\t\tchar: 'n',\n\t\tdescription: 'The name of the group',\n\t}),\n\tdescription: Flags.string({\n\t\tdescription: 'Description of the group',\n\t\tparse: utilities.unescapeSlashes,\n\t}),\n\t'external-sync-identifier': Flags.string({\n\t\tdescription:\n\t\t\t'group identifier for groups coming from an external source',\n\t}),\n\tprovenance: Flags.string({\n\t\tdescription: 'Track the external source where the group is coming from',\n\t}),\n\tinvite: Flags.string({\n\t\tchar: 'i',\n\t\tdescription: 'Specifies who can invite the group to collaborate',\n\t\toptions: ['admins_only', 'admins_and_members', 'all_managed_users'],\n\t}),\n\t'view-members': Flags.string({\n\t\tchar: 'm',\n\t\tdescription: 'Specifies who can view the members of the group',\n\t\toptions: ['admins_only', 'admins_and_members', 'all_managed_users'],\n\t}),\n};\n\nGroupsUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the group to update',\n\t}),\n};\n\nmodule.exports = GroupsUpdateCommand;\n"
  },
  {
    "path": "src/commands/hubs/collaborations/create.js",
    "content": "'use strict';\n\nconst { Args, Flags } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nconst HUB_COLLABORATION_ROLES = ['editor', 'viewer', 'co-owner'];\n\nfunction getAccessibleBy(flags) {\n\tif (flags['user-id']) {\n\t\treturn {\n\t\t\ttype: 'user',\n\t\t\tid: flags['user-id'],\n\t\t};\n\t}\n\n\tif (flags['group-id']) {\n\t\treturn {\n\t\t\ttype: 'group',\n\t\t\tid: flags['group-id'],\n\t\t};\n\t}\n\n\tif (flags.login) {\n\t\treturn {\n\t\t\ttype: 'user',\n\t\t\tlogin: flags.login,\n\t\t};\n\t}\n\n\tthrow new Error('Please provide one of --user-id, --group-id, or --login.');\n}\n\nclass HubsCreateCollaborationCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(HubsCreateCollaborationCommand);\n\t\tconst requestBody = {\n\t\t\thub: {\n\t\t\t\tid: args.id,\n\t\t\t\ttype: 'hubs',\n\t\t\t},\n\t\t\taccessibleBy: getAccessibleBy(flags),\n\t\t\trole: flags.role,\n\t\t};\n\n\t\tconst collaboration =\n\t\t\tawait this.tsClient.hubCollaborations.createHubCollaborationV2025R0(\n\t\t\t\trequestBody\n\t\t\t);\n\t\tawait this.output(collaboration.rawData ?? collaboration);\n\t}\n}\nHubsCreateCollaborationCommand.aliases = ['hubs:collaborations:add'];\nHubsCreateCollaborationCommand.description =\n\t'Adds a collaboration with a specific role for a single user or a single group to a Box Hub. Collaborations can be created using email address, user IDs, or group IDs';\nHubsCreateCollaborationCommand.examples = [\n\t'box hubs:collaborations:create 12345 --role editor --user-id 22222',\n\t'box hubs:collaborations:create 12345 --role viewer --group-id 33333',\n\t'box hubs:collaborations:create 12345 --role co-owner --login jdoe@example.com',\n];\nHubsCreateCollaborationCommand._endpoint = 'post_hub_collaborations';\n\nHubsCreateCollaborationCommand.flags = {\n\t...BoxCommand.flags,\n\trole: Flags.string({\n\t\tchar: 'r',\n\t\tdescription:\n\t\t\t'Role to grant for the hub collaboration. One of: editor, viewer, co-owner',\n\t\trequired: true,\n\t\toptions: HUB_COLLABORATION_ROLES,\n\t}),\n\t'user-id': Flags.string({\n\t\tdescription: 'Collaborate a user by Box user ID',\n\t\texclusive: ['group-id', 'login'],\n\t}),\n\t'group-id': Flags.string({\n\t\tdescription: 'Collaborate a group by Box group ID',\n\t\texclusive: ['user-id', 'login'],\n\t}),\n\tlogin: Flags.string({\n\t\tdescription: 'Collaborate a user by email address',\n\t\texclusive: ['user-id', 'group-id'],\n\t}),\n};\n\nHubsCreateCollaborationCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the Box Hub',\n\t}),\n};\n\nmodule.exports = HubsCreateCollaborationCommand;\n"
  },
  {
    "path": "src/commands/hubs/collaborations/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass HubsDeleteCollaborationCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(HubsDeleteCollaborationCommand);\n\t\tawait this.tsClient.hubCollaborations.deleteHubCollaborationByIdV2025R0(\n\t\t\targs.id\n\t\t);\n\t\tthis.info(`Deleted hub collaboration ${args.id}`);\n\t}\n}\n\nHubsDeleteCollaborationCommand.description = 'Delete a single Box Hub collaboration';\nHubsDeleteCollaborationCommand.examples = [\n\t'box hubs:collaborations:delete 99999',\n];\nHubsDeleteCollaborationCommand._endpoint = 'delete_hub_collaborations_id';\n\nHubsDeleteCollaborationCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nHubsDeleteCollaborationCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the hub collaboration to delete',\n\t}),\n};\n\nmodule.exports = HubsDeleteCollaborationCommand;\n"
  },
  {
    "path": "src/commands/hubs/collaborations/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass HubsGetCollaborationCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(HubsGetCollaborationCommand);\n\t\tconst collaboration =\n\t\t\tawait this.tsClient.hubCollaborations.getHubCollaborationByIdV2025R0(\n\t\t\t\targs.id\n\t\t\t);\n\t\tawait this.output(collaboration.rawData ?? collaboration);\n\t}\n}\n\nHubsGetCollaborationCommand.description =\n\t'Retrieves details for a Box Hub collaboration by collaboration ID';\nHubsGetCollaborationCommand.examples = ['box hubs:collaborations:get 99999'];\nHubsGetCollaborationCommand._endpoint = 'get_hub_collaborations_id';\n\nHubsGetCollaborationCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nHubsGetCollaborationCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the hub collaboration',\n\t}),\n};\n\nmodule.exports = HubsGetCollaborationCommand;\n"
  },
  {
    "path": "src/commands/hubs/collaborations/index.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\nconst PaginationUtilities = require('../../../pagination-utils');\n\nclass HubsListCollaborationsCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(HubsListCollaborationsCommand);\n\t\tconst queryParams = {\n\t\t\thubId: args.id,\n\t\t};\n\n\t\tconst collaborations = await this.markerPagination(\n\t\t\t(pageQueryParams) =>\n\t\t\t\tthis.tsClient.hubCollaborations.getHubCollaborationsV2025R0(\n\t\t\t\t\tpageQueryParams\n\t\t\t\t),\n\t\t\tqueryParams\n\t\t);\n\t\tawait this.output(collaborations);\n\t}\n}\n\nHubsListCollaborationsCommand.aliases = ['hubs:collaborations:list'];\nHubsListCollaborationsCommand.description = 'List collaborations for a Box Hub';\nHubsListCollaborationsCommand.examples = [\n\t'box hubs:collaborations 12345',\n\t'box hubs:collaborations 12345 --max-items 50',\n];\nHubsListCollaborationsCommand._endpoint = 'get_hub_collaborations';\n\nHubsListCollaborationsCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nHubsListCollaborationsCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the Box Hub',\n\t}),\n};\n\nmodule.exports = HubsListCollaborationsCommand;\n"
  },
  {
    "path": "src/commands/hubs/collaborations/update.js",
    "content": "'use strict';\n\nconst { Args, Flags } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nconst HUB_COLLABORATION_ROLES = ['editor', 'viewer', 'co-owner'];\n\nclass HubsUpdateCollaborationCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(HubsUpdateCollaborationCommand);\n\t\tconst collaboration =\n\t\t\tawait this.tsClient.hubCollaborations.updateHubCollaborationByIdV2025R0(\n\t\t\t\targs.id,\n\t\t\t\t{\n\t\t\t\t\trole: flags.role,\n\t\t\t\t}\n\t\t\t);\n\t\tawait this.output(collaboration.rawData ?? collaboration);\n\t}\n}\n\nHubsUpdateCollaborationCommand.description = 'Updates a Box Hub collaboration. Can be used to change the Box Hub role.';\nHubsUpdateCollaborationCommand.examples = [\n\t'box hubs:collaborations:update 99999 --role viewer',\n];\nHubsUpdateCollaborationCommand._endpoint = 'put_hub_collaborations_id';\n\nHubsUpdateCollaborationCommand.flags = {\n\t...BoxCommand.flags,\n\trole: Flags.string({\n\t\tchar: 'r',\n\t\tdescription:\n\t\t\t'Updated role for the hub collaboration. One of: editor, viewer, co-owner',\n\t\trequired: true,\n\t\toptions: HUB_COLLABORATION_ROLES,\n\t}),\n};\n\nHubsUpdateCollaborationCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the hub collaboration to update',\n\t}),\n};\n\nmodule.exports = HubsUpdateCollaborationCommand;\n"
  },
  {
    "path": "src/commands/hubs/copy.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass HubsCopyCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(HubsCopyCommand);\n\t\tconst requestBody = {};\n\n\t\tif (flags.title) {\n\t\t\trequestBody.title = flags.title;\n\t\t}\n\t\tif (flags.description) {\n\t\t\trequestBody.description = flags.description;\n\t\t}\n\n\t\tconst hub = await this.tsClient.hubs.copyHubV2025R0(args.id, requestBody);\n\t\tawait this.output(hub.rawData ?? hub);\n\t}\n}\n\nHubsCopyCommand.description = 'Copy a Box Hub';\nHubsCopyCommand.examples = [\n\t'box hubs:copy 12345 --title \"Copied hub title\" --description \"Copied hub description\"',\n];\nHubsCopyCommand._endpoint = 'post_hubs_id_copy';\n\nHubsCopyCommand.flags = {\n\t...BoxCommand.flags,\n\ttitle: Flags.string({\n\t\tchar: 'T',\n\t\tdescription: 'Optional title override for the copied hub',\n\t}),\n\tdescription: Flags.string({\n\t\tchar: 'd',\n\t\tdescription: 'Optional description override for the copied hub',\n\t\tparse: utilities.unescapeSlashes,\n\t}),\n};\n\nHubsCopyCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the Box Hub to copy',\n\t}),\n};\n\nmodule.exports = HubsCopyCommand;\n"
  },
  {
    "path": "src/commands/hubs/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass HubsCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(HubsCreateCommand);\n\t\tconst requestBody = {\n\t\t\ttitle: args.title,\n\t\t};\n\n\t\tif (flags.description) {\n\t\t\trequestBody.description = flags.description;\n\t\t}\n\n\t\tconst hub = await this.tsClient.hubs.createHubV2025R0(requestBody);\n\t\tawait this.output(hub.rawData ?? hub);\n\t}\n}\n\nHubsCreateCommand.description = 'Create a new Box Hub';\nHubsCreateCommand.examples = ['box hubs:create \"Roadmap Hub\" --description \"Q3 planning hub\"'];\nHubsCreateCommand._endpoint = 'post_hubs';\n\nHubsCreateCommand.flags = {\n\t...BoxCommand.flags,\n\tdescription: Flags.string({\n\t\tchar: 'd',\n\t\tdescription: 'Description of the Box Hub',\n\t\tparse: utilities.unescapeSlashes,\n\t}),\n};\n\nHubsCreateCommand.args = {\n\ttitle: Args.string({\n\t\tname: 'title',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Title for the Box Hub',\n\t}),\n};\n\nmodule.exports = HubsCreateCommand;\n"
  },
  {
    "path": "src/commands/hubs/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass HubsDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(HubsDeleteCommand);\n\t\tawait this.tsClient.hubs.deleteHubByIdV2025R0(args.id);\n\t\tthis.info(`Deleted hub ${args.id}`);\n\t}\n}\n\nHubsDeleteCommand.description = 'Delete a Box Hub';\nHubsDeleteCommand.examples = ['box hubs:delete 12345'];\nHubsDeleteCommand._endpoint = 'delete_hubs_id';\n\nHubsDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nHubsDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the Box Hub to delete',\n\t}),\n};\n\nmodule.exports = HubsDeleteCommand;\n"
  },
  {
    "path": "src/commands/hubs/document/blocks.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\nconst PaginationUtilities = require('../../../pagination-utils');\n\nclass HubsListDocumentBlocksCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(HubsListDocumentBlocksCommand);\n\t\tconst queryParams = {\n\t\t\thubId: args.id,\n\t\t\tpageId: args.pageId,\n\t\t};\n\n\t\tconst blocks = await this.markerPagination(\n\t\t\t(pageQueryParams) =>\n\t\t\t\tthis.tsClient.hubDocument.getHubDocumentBlocksV2025R0(\n\t\t\t\t\tpageQueryParams\n\t\t\t\t),\n\t\t\tqueryParams\n\t\t);\n\t\tawait this.output(blocks);\n\t}\n}\n\nHubsListDocumentBlocksCommand.aliases = ['hubs:document:blocks:list'];\nHubsListDocumentBlocksCommand.description =\n\t'Retrieve sorted Hub Document Blocks for a specific hub document page, excluding items. Results are organized by parent_id and include only blocks on that page, not sub pages or their content blocks.';\nHubsListDocumentBlocksCommand.examples = [\n\t'box hubs:document:blocks 12345 55c8361a-012a-4fa1-a724-b7ef1cd87865',\n\t'box hubs:document:blocks 12345 55c8361a-012a-4fa1-a724-b7ef1cd87865 --max-items 50',\n];\nHubsListDocumentBlocksCommand._endpoint = 'get_hub_document_blocks';\n\nHubsListDocumentBlocksCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nHubsListDocumentBlocksCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the Box Hub',\n\t}),\n\tpageId: Args.string({\n\t\tname: 'page-id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the page in the Box Hub document',\n\t}),\n};\n\nmodule.exports = HubsListDocumentBlocksCommand;\n"
  },
  {
    "path": "src/commands/hubs/document/pages.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\nconst PaginationUtilities = require('../../../pagination-utils');\n\nclass HubsListDocumentPagesCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(HubsListDocumentPagesCommand);\n\t\tconst queryParams = {\n\t\t\thubId: args.id,\n\t\t};\n\n\t\tconst pages = await this.markerPagination(\n\t\t\t(pageQueryParams) =>\n\t\t\t\tthis.tsClient.hubDocument.getHubDocumentPagesV2025R0(\n\t\t\t\t\tpageQueryParams\n\t\t\t\t),\n\t\t\tqueryParams\n\t\t);\n\t\tawait this.output(pages);\n\t}\n}\n\nHubsListDocumentPagesCommand.aliases = ['hubs:document:pages:list'];\nHubsListDocumentPagesCommand.description = 'Retrieves a list of Hub Document Pages for the specified hub. Includes both root-level pages and sub pages';\nHubsListDocumentPagesCommand.examples = [\n\t'box hubs:document:pages 12345',\n\t'box hubs:document:pages 12345 --max-items 50',\n];\nHubsListDocumentPagesCommand._endpoint = 'get_hub_document_pages';\n\nHubsListDocumentPagesCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nHubsListDocumentPagesCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the Box Hub',\n\t}),\n};\n\nmodule.exports = HubsListDocumentPagesCommand;\n"
  },
  {
    "path": "src/commands/hubs/enterprise.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass HubsEnterpriseListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(HubsEnterpriseListCommand);\n\t\tconst queryParams = {};\n\n\t\tif (flags.query) {\n\t\t\tqueryParams.query = flags.query;\n\t\t}\n\t\tif (flags.sort) {\n\t\t\tqueryParams.sort = flags.sort;\n\t\t}\n\t\tif (flags.direction) {\n\t\t\tqueryParams.direction = flags.direction;\n\t\t}\n\n\t\tconst hubs = await this.markerPagination(\n\t\t\t(pageQueryParams) =>\n\t\t\t\tthis.tsClient.hubs.getEnterpriseHubsV2025R0(pageQueryParams),\n\t\t\tqueryParams\n\t\t);\n\t\tawait this.output(hubs);\n\t}\n}\n\nHubsEnterpriseListCommand.description =\n\t'List Box Hubs across the enterprise. This call requires an admin or hub co-admin of an enterprise with GCM scope. Otherwise, Box returns a 403 status code with the message `The request requires higher privileges than provided by the access token.` See https://developer.box.com/guides/api-calls/permissions-and-errors/scopes#global-content-manager-gcm';\nHubsEnterpriseListCommand.examples = [\n\t'box hubs:enterprise',\n\t'box hubs:enterprise --query \"Roadmap\" --sort updated_at --direction DESC',\n];\nHubsEnterpriseListCommand._endpoint = 'get_enterprise_hubs';\n\nHubsEnterpriseListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n\tquery: Flags.string({\n\t\tdescription: 'Search query for enterprise Box Hubs',\n\t}),\n\tsort: Flags.string({\n\t\tdescription:\n\t\t\t'Sort field for hubs. One of: name, updated_at, last_accessed_at, view_count, relevance',\n\t\toptions: [\n\t\t\t'name',\n\t\t\t'updated_at',\n\t\t\t'last_accessed_at',\n\t\t\t'view_count',\n\t\t\t'relevance',\n\t\t],\n\t}),\n\tdirection: Flags.string({\n\t\tdescription: 'Sort direction. One of: ASC, DESC',\n\t\toptions: ['ASC', 'DESC'],\n\t}),\n};\n\nmodule.exports = HubsEnterpriseListCommand;\n"
  },
  {
    "path": "src/commands/hubs/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass HubsGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(HubsGetCommand);\n\t\tconst hub = await this.tsClient.hubs.getHubByIdV2025R0(args.id);\n\t\tawait this.output(hub.rawData ?? hub);\n\t}\n}\n\nHubsGetCommand.description = 'Get details for a Box Hub';\nHubsGetCommand.examples = ['box hubs:get 12345'];\nHubsGetCommand._endpoint = 'get_hubs_id';\n\nHubsGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nHubsGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the Box Hub',\n\t}),\n};\n\nmodule.exports = HubsGetCommand;\n"
  },
  {
    "path": "src/commands/hubs/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass HubsListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(HubsListCommand);\n\t\tconst queryParams = {};\n\n\t\tif (flags.query) {\n\t\t\tqueryParams.query = flags.query;\n\t\t}\n\t\tif (flags.scope) {\n\t\t\tqueryParams.scope = flags.scope;\n\t\t}\n\t\tif (flags.sort) {\n\t\t\tqueryParams.sort = flags.sort;\n\t\t}\n\t\tif (flags.direction) {\n\t\t\tqueryParams.direction = flags.direction;\n\t\t}\n\n\t\tconst hubs = await this.markerPagination(\n\t\t\t(pageQueryParams) => this.tsClient.hubs.getHubsV2025R0(pageQueryParams),\n\t\t\tqueryParams\n\t\t);\n\t\tawait this.output(hubs);\n\t}\n}\n\nHubsListCommand.aliases = ['hubs:list'];\nHubsListCommand.description = 'List Box Hubs for the current user';\nHubsListCommand.examples = [\n\t'box hubs',\n\t'box hubs --query \"Product\" --scope editable --sort name --direction ASC',\n];\nHubsListCommand._endpoint = 'get_hubs';\n\nHubsListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n\tquery: Flags.string({\n\t\tdescription: 'Search query for Box Hubs',\n\t}),\n\tscope: Flags.string({\n\t\tdescription:\n\t\t\t'Scope of hubs to retrieve. One of: editable, view_only, all',\n\t\toptions: ['editable', 'view_only', 'all'],\n\t}),\n\tsort: Flags.string({\n\t\tdescription:\n\t\t\t'Sort field for hubs. One of: name, updated_at, last_accessed_at, view_count, relevance',\n\t\toptions: [\n\t\t\t'name',\n\t\t\t'updated_at',\n\t\t\t'last_accessed_at',\n\t\t\t'view_count',\n\t\t\t'relevance',\n\t\t],\n\t}),\n\tdirection: Flags.string({\n\t\tdescription: 'Sort direction. One of: ASC, DESC',\n\t\toptions: ['ASC', 'DESC'],\n\t}),\n};\n\nmodule.exports = HubsListCommand;\n"
  },
  {
    "path": "src/commands/hubs/items/index.js",
    "content": "'use strict';\n\nconst { Args, Flags } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\nconst PaginationUtilities = require('../../../pagination-utils');\n\nclass HubsListItemsCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(HubsListItemsCommand);\n\t\tconst queryParams = {\n\t\t\thubId: args.id,\n\t\t};\n\n\t\tif (flags['parent-id']) {\n\t\t\tqueryParams.parentId = flags['parent-id'];\n\t\t}\n\n\t\tconst items = await this.markerPagination(\n\t\t\t(pageQueryParams) =>\n\t\t\t\tthis.tsClient.hubItems.getHubItemsV2025R0(pageQueryParams),\n\t\t\tqueryParams\n\t\t);\n\t\tawait this.output(items);\n\t}\n}\n\nHubsListItemsCommand.aliases = ['hubs:items:list'];\nHubsListItemsCommand.description = 'List items in a Box Hub';\nHubsListItemsCommand.examples = [\n\t'box hubs:items 12345',\n\t'box hubs:items 12345 --parent-id 67890 --max-items 50',\n];\nHubsListItemsCommand._endpoint = 'get_hub_items';\n\nHubsListItemsCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n\t'parent-id': Flags.string({\n\t\tdescription:\n\t\t\t'Filter to items that belong to a specific item list block in the Box Hub',\n\t}),\n};\n\nHubsListItemsCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the Box Hub',\n\t}),\n};\n\nmodule.exports = HubsListItemsCommand;\n"
  },
  {
    "path": "src/commands/hubs/items/manage.js",
    "content": "'use strict';\n\nconst { Args, Flags } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\nconst utilities = require('../../../util');\n\nconst HUB_ITEM_TYPES = ['file', 'folder', 'web_link'];\nconst HUB_ITEM_OPERATION_KEYS = ['id', 'type', 'parent-id'];\n\nfunction parseHubItemOperation(action, input) {\n\tconst parsed = utilities.parseStringToObject(input, HUB_ITEM_OPERATION_KEYS);\n\tconst operation = {\n\t\taction,\n\t\titem: {},\n\t};\n\n\tif (!parsed.id) {\n\t\tthrow new Error('Hub item operations require an id key.');\n\t}\n\n\tif (!parsed.type) {\n\t\tthrow new Error('Hub item operations require a type key.');\n\t}\n\n\tif (!HUB_ITEM_TYPES.includes(parsed.type)) {\n\t\tthrow new Error(\n\t\t\t`Invalid hub item type '${parsed.type}'. Supported types are ${HUB_ITEM_TYPES.join(', ')}.`\n\t\t);\n\t}\n\n\toperation.item.id = parsed.id;\n\toperation.item.type = parsed.type;\n\n\tif (parsed['parent-id']) {\n\t\toperation.parentId = parsed['parent-id'];\n\t}\n\n\treturn operation;\n}\n\nclass HubsManageItemsCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(HubsManageItemsCommand);\n\t\tconst operations = [...(flags.add || []), ...(flags.remove || [])];\n\n\t\tif (operations.length === 0) {\n\t\tthrow new Error('Please provide at least one --add or --remove flag.');\n\t\t}\n\n\t\tconst response = await this.tsClient.hubItems.manageHubItemsV2025R0(\n\t\t\targs.id,\n\t\t\t{ operations }\n\t\t);\n\t\tawait this.output(response.rawData ?? response);\n\t}\n}\n\nHubsManageItemsCommand.description = 'Add or remove items in a Box Hub';\nHubsManageItemsCommand.examples = [\n\t'box hubs:items:manage 12345 --add id=11111,type=file,parent-id=67890',\n\t'box hubs:items:manage 12345 --remove id=22222,type=folder',\n];\nHubsManageItemsCommand._endpoint = 'post_hubs_id_manage_items';\n\nHubsManageItemsCommand.flags = {\n\t...BoxCommand.flags,\n\tadd: Flags.string({\n\t\tdescription:\n\t\t\t'Add an item to the Box Hub. Format: id=ITEM_ID,type=TYPE,parent-id=PARENT_ID. Supported types are file, folder, web_link. The parent-id is the ID of the parent block to add the item to. It must be an Item List block. If not provided, the item will be added to the first page\\'s first Item List block.',\n\t\tmultiple: true,\n\t\tparse(input) {\n\t\t\treturn parseHubItemOperation('add', input);\n\t\t},\n\t}),\n\tremove: Flags.string({\n\t\tdescription:\n\t\t\t'Remove an item from the Box Hub. Format: id=ITEM_ID,type=TYPE. Supported types are file, folder, web_link.',\n\t\tmultiple: true,\n\t\tparse(input) {\n\t\t\treturn parseHubItemOperation('remove', input);\n\t\t},\n\t}),\n};\n\nHubsManageItemsCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the Box Hub',\n\t}),\n};\n\nmodule.exports = HubsManageItemsCommand;\n"
  },
  {
    "path": "src/commands/hubs/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass HubsUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(HubsUpdateCommand);\n\t\tconst requestBody = {};\n\n\t\tif (flags.title) {\n\t\t\trequestBody.title = flags.title;\n\t\t}\n\t\tif (flags.description) {\n\t\t\trequestBody.description = flags.description;\n\t\t}\n\t\tif (Object.hasOwn(flags, 'ai-enabled')) {\n\t\t\trequestBody.isAiEnabled = flags['ai-enabled'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'collaboration-restricted-to-enterprise')) {\n\t\t\trequestBody.isCollaborationRestrictedToEnterprise =\n\t\t\t\tflags['collaboration-restricted-to-enterprise'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'can-non-owners-invite')) {\n\t\t\trequestBody.canNonOwnersInvite = flags['can-non-owners-invite'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'can-shared-link-be-created')) {\n\t\t\trequestBody.canSharedLinkBeCreated =\n\t\t\t\tflags['can-shared-link-be-created'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'can-public-shared-link-be-created')) {\n\t\t\trequestBody.canPublicSharedLinkBeCreated =\n\t\t\t\tflags['can-public-shared-link-be-created'];\n\t\t}\n\n\t\tif (Object.keys(requestBody).length === 0) {\n\t\t\tthis.error('Please provide at least one update flag.');\n\t\t}\n\n\t\tconst hub = await this.tsClient.hubs.updateHubByIdV2025R0(\n\t\t\targs.id,\n\t\t\trequestBody\n\t\t);\n\t\tawait this.output(hub.rawData ?? hub);\n\t}\n}\n\nHubsUpdateCommand.description = 'Update a Box Hub';\nHubsUpdateCommand.examples = [\n\t'box hubs:update 12345 --title \"Updated title\" --ai-enabled',\n];\nHubsUpdateCommand._endpoint = 'put_hubs_id';\n\nHubsUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\ttitle: Flags.string({\n\t\tchar: 'T',\n\t\tdescription: 'Updated title for the Box Hub',\n\t}),\n\tdescription: Flags.string({\n\t\tchar: 'd',\n\t\tdescription: 'Updated description for the Box Hub',\n\t\tparse: utilities.unescapeSlashes,\n\t}),\n\t'ai-enabled': Flags.boolean({\n\t\tdescription: 'Enable or disable AI features for this Box Hub',\n\t\tallowNo: true,\n\t}),\n\t'collaboration-restricted-to-enterprise': Flags.boolean({\n\t\tdescription: 'Restrict collaboration to enterprise users only',\n\t\tallowNo: true,\n\t}),\n\t'can-non-owners-invite': Flags.boolean({\n\t\tdescription: 'Allow non-owners to invite collaborators',\n\t\tallowNo: true,\n\t}),\n\t'can-shared-link-be-created': Flags.boolean({\n\t\tdescription: 'Allow shared links for this Box Hub',\n\t\tallowNo: true,\n\t}),\n\t'can-public-shared-link-be-created': Flags.boolean({\n\t\tdescription: 'Allow public shared links for this Box Hub',\n\t\tallowNo: true,\n\t}),\n};\n\nHubsUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the Box Hub to update',\n\t}),\n};\n\nmodule.exports = HubsUpdateCommand;\n"
  },
  {
    "path": "src/commands/integration-mappings/slack/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst BoxCLIError = require('../../../cli-error');\nconst { Flags, Args } = require('@oclif/core');\n\nclass IntegrationMappingsSlackCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tIntegrationMappingsSlackCreateCommand\n\t\t);\n\t\tlet body = {\n\t\t\tbox_item: {\n\t\t\t\ttype: 'folder',\n\t\t\t\tid: args.boxItemID,\n\t\t\t},\n\t\t\tpartner_item: {\n\t\t\t\ttype: 'channel',\n\t\t\t\tid: args.channelID,\n\t\t\t},\n\t\t};\n\t\tif (flags['slack-workspace-id']) {\n\t\t\tbody.partner_item.slack_workspace_id = flags['slack-workspace-id'];\n\t\t} else if (flags['slack-org-id']) {\n\t\t\tbody.partner_item.slack_org_id = flags['slack-org-id'];\n\t\t} else {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Either the --slack-workspace-id or --slack-org-id flag must be passed'\n\t\t\t);\n\t\t}\n\t\tif (Object.hasOwn(flags, 'disable-access-management')) {\n\t\t\tbody.options = {\n\t\t\t\tis_access_management_disabled:\n\t\t\t\t\tflags['disable-access-management'],\n\t\t\t};\n\t\t}\n\n\t\tlet integrationMapping =\n\t\t\tawait this.client.integrationMappings.createSlackIntegrationMapping(\n\t\t\t\tbody\n\t\t\t);\n\t\tawait this.output(integrationMapping);\n\t}\n}\n\nIntegrationMappingsSlackCreateCommand.description =\n\t'Create Slack integration mapping';\nIntegrationMappingsSlackCreateCommand.examples = [\n\t'box integration-mappings:slack:create 123 AB89X56Y --slack-org-id 789',\n\t'box integration-mappings:slack:create 123 AB89X56Y --slack-workspace-id 999 --disable-access-management',\n];\nIntegrationMappingsSlackCreateCommand._endpoint =\n\t'post_integration_mappings_slack';\n\nIntegrationMappingsSlackCreateCommand.flags = {\n\t...BoxCommand.flags,\n\t'slack-workspace-id': Flags.string({\n\t\tdescription:\n\t\t\t'ID of the Slack workspace with which the item would be associated',\n\t\texclusive: ['slack-org-id'],\n\t}),\n\t'slack-org-id': Flags.string({\n\t\tdescription:\n\t\t\t'ID of the Slack organization with which the item would be associated',\n\t\texclusive: ['slack-workspace-id'],\n\t}),\n\t'disable-access-management': Flags.boolean({\n\t\tdescription:\n\t\t\t'Indicates whether or not channel member access to the underlying box item should be automatically managed. ' +\n\t\t\t'Depending on type of channel, access is managed through creating collaborations or shared links.',\n\t\tallowNo: true,\n\t}),\n};\n\nIntegrationMappingsSlackCreateCommand.args = {\n\tboxItemID: Args.string({\n\t\tname: 'boxItemID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the mapped folder',\n\t}),\n\tchannelID: Args.string({\n\t\tname: 'channelID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the mapped Slack channel',\n\t}),\n};\n\nmodule.exports = IntegrationMappingsSlackCreateCommand;\n"
  },
  {
    "path": "src/commands/integration-mappings/slack/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass IntegrationMappingsSlackDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(\n\t\t\tIntegrationMappingsSlackDeleteCommand\n\t\t);\n\n\t\tawait this.client.integrationMappings.deleteSlackIntegrationMappingById(\n\t\t\t{ integration_mapping_id: args.id }\n\t\t);\n\t\tthis.info(`Deleted Slack integration mapping ${args.id}`);\n\t}\n}\n\nIntegrationMappingsSlackDeleteCommand.description =\n\t'Delete Slack integration mapping';\nIntegrationMappingsSlackDeleteCommand.examples = [\n\t'box integration-mappings:slack:delete 123',\n];\nIntegrationMappingsSlackDeleteCommand._endpoint =\n\t'delete_integration_mappings_slack_id';\n\nIntegrationMappingsSlackDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nIntegrationMappingsSlackDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the integration mapping',\n\t}),\n};\n\nmodule.exports = IntegrationMappingsSlackDeleteCommand;\n"
  },
  {
    "path": "src/commands/integration-mappings/slack/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags } = require('@oclif/core');\nconst PaginationUtilities = require('../../../pagination-utils');\n\nclass IntegrationMappingsSlackListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(IntegrationMappingsSlackListCommand);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags['partner-item-id']) {\n\t\t\toptions.partner_item_id = flags['partner-item-id'];\n\t\t}\n\t\tif (flags['box-item-id']) {\n\t\t\toptions.box_item_id = flags['box-item-id'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'manually-created')) {\n\t\t\toptions.is_manually_created = flags['manually-created'];\n\t\t}\n\n\t\tlet slackIntegrationMappings =\n\t\t\tawait this.client.integrationMappings.getSlackIntegrationMappings(\n\t\t\t\toptions\n\t\t\t);\n\t\tawait this.output(slackIntegrationMappings);\n\t}\n}\n\nIntegrationMappingsSlackListCommand.aliases = [\n\t'integration-mappings:slack:list',\n];\n\nIntegrationMappingsSlackListCommand.description =\n\t'List Slack integration mappings';\nIntegrationMappingsSlackListCommand.examples = [\n\t'box integration-mappings:slack --partner-item-id 123 --manually-created',\n\t'box integration-mappings:slack --box-item-id 456 --no-manually-created',\n];\nIntegrationMappingsSlackListCommand._endpoint =\n\t'get_integration_mappings_slack';\n\nIntegrationMappingsSlackListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n\t'partner-item-id': Flags.string({\n\t\thidden: false,\n\t\tdescription:\n\t\t\t'ID of the mapped Slack channel, for which the mapping should be returned',\n\t}),\n\t'box-item-id': Flags.string({\n\t\thidden: false,\n\t\tdescription:\n\t\t\t'ID of the mapped Box folder, for which the mapping should be returned',\n\t}),\n\t'manually-created': Flags.boolean({\n\t\tdescription: 'Whether the mapping has been manually created',\n\t\tallowNo: true,\n\t}),\n};\n\nmodule.exports = IntegrationMappingsSlackListCommand;\n"
  },
  {
    "path": "src/commands/integration-mappings/slack/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass IntegrationMappingsSlackUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tIntegrationMappingsSlackUpdateCommand\n\t\t);\n\t\tlet options = { integration_mapping_id: args.id };\n\t\tlet body = {};\n\n\t\tif (flags['box-item-id']) {\n\t\t\tbody.box_item = {\n\t\t\t\tid: flags['box-item-id'],\n\t\t\t\ttype: 'folder',\n\t\t\t};\n\t\t}\n\t\tif (Object.hasOwn(flags, 'disable-access-management')) {\n\t\t\tbody.options = {\n\t\t\t\tis_access_management_disabled:\n\t\t\t\t\tflags['disable-access-management'],\n\t\t\t};\n\t\t}\n\n\t\tlet integrationMapping =\n\t\t\tawait this.client.integrationMappings.updateSlackIntegrationMapping(\n\t\t\t\tbody,\n\t\t\t\toptions\n\t\t\t);\n\t\tawait this.output(integrationMapping);\n\t}\n}\n\nIntegrationMappingsSlackUpdateCommand.description =\n\t'Update Slack integration mapping';\nIntegrationMappingsSlackUpdateCommand.examples = [\n\t'box integration-mappings:slack:update 123 --box-item-id 789 --disable-access-management',\n];\nIntegrationMappingsSlackUpdateCommand._endpoint =\n\t'put_integration_mappings_slack_id';\n\nIntegrationMappingsSlackUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\t'box-item-id': Flags.string({\n\t\tdescription: 'ID of the mapped folder',\n\t}),\n\t'disable-access-management': Flags.boolean({\n\t\tdescription:\n\t\t\t'Indicates whether or not channel member access to the underlying box item should be automatically managed. ' +\n\t\t\t'Depending on type of channel, access is managed through creating collaborations or shared links.',\n\t\tallowNo: true,\n\t}),\n};\n\nIntegrationMappingsSlackUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of an integration mapping',\n\t}),\n};\n\nmodule.exports = IntegrationMappingsSlackUpdateCommand;\n"
  },
  {
    "path": "src/commands/integration-mappings/teams/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Args } = require('@oclif/core');\n\nclass IntegrationMappingsTeamsCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(\n\t\t\tIntegrationMappingsTeamsCreateCommand\n\t\t);\n\t\tlet body = {\n\t\t\tboxItem: {\n\t\t\t\ttype: 'folder',\n\t\t\t\tid: args.boxItemID,\n\t\t\t},\n\t\t\tpartnerItem: {\n\t\t\t\ttype: args.partnerItemType,\n\t\t\t\tid: args.partnerItemID,\n\t\t\t\tteamId: args.partnerItemTeamID,\n\t\t\t\ttenantId: args.partnerItemTenantID,\n\t\t\t},\n\t\t};\n\n\t\tlet integrationMapping =\n\t\t\tawait this.tsClient.integrationMappings.createTeamsIntegrationMapping(\n\t\t\t\tbody\n\t\t\t);\n\t\tdelete integrationMapping.rawData;\n\t\tawait this.output(integrationMapping);\n\t}\n}\n\nIntegrationMappingsTeamsCreateCommand.description =\n\t'Create Teams integration mapping';\nIntegrationMappingsTeamsCreateCommand.examples = [\n\t'box integration-mappings:teams:create 123 19%ABCD-Avgfggkggyftdtfgghjhkhkhh%40thread:tacv2 hjgjgjg-bhhj-564a-b643-hghgj685u abcd-defg-1235-7890',\n];\nIntegrationMappingsTeamsCreateCommand._endpoint =\n\t'post_integration_mappings_teams';\n\nIntegrationMappingsTeamsCreateCommand.args = {\n\tboxItemID: Args.string({\n\t\tname: 'boxItemID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the mapped folder',\n\t}),\n\tpartnerItemID: Args.string({\n\t\tname: 'partnerItemID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the mapped item',\n\t}),\n\tpartnerItemType: Args.string({\n\t\tname: 'partnerItemType',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Type of the mapped item, value is one of: channel, team',\n\t}),\n\tpartnerItemTeamID: Args.string({\n\t\tname: 'partnerItemTeamID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the team that is registered with Microsoft Teams',\n\t}),\n\tpartnerItemTenantID: Args.string({\n\t\tname: 'partnerItemTenantID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the tenant that is registered with Microsoft Teams',\n\t}),\n};\n\nmodule.exports = IntegrationMappingsTeamsCreateCommand;\n"
  },
  {
    "path": "src/commands/integration-mappings/teams/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass IntegrationMappingsTeamsDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(\n\t\t\tIntegrationMappingsTeamsDeleteCommand\n\t\t);\n\n\t\tawait this.tsClient.integrationMappings.deleteTeamsIntegrationMappingById(\n\t\t\targs.id\n\t\t);\n\t\tthis.info(`Deleted Teams integration mapping ${args.id}`);\n\t}\n}\n\nIntegrationMappingsTeamsDeleteCommand.description =\n\t'Delete Teams integration mapping';\nIntegrationMappingsTeamsDeleteCommand.examples = [\n\t'box integration-mappings:teams:delete 123',\n];\nIntegrationMappingsTeamsDeleteCommand._endpoint =\n\t'delete_integration_mappings_teams_id';\n\nIntegrationMappingsTeamsDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nIntegrationMappingsTeamsDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the integration mapping',\n\t}),\n};\n\nmodule.exports = IntegrationMappingsTeamsDeleteCommand;\n"
  },
  {
    "path": "src/commands/integration-mappings/teams/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags } = require('@oclif/core');\nconst PaginationUtilities = require('../../../pagination-utils');\n\nclass IntegrationMappingsTeamsListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(IntegrationMappingsTeamsListCommand);\n\t\tlet options = {};\n\n\t\tif (flags['partner-item-id']) {\n\t\t\toptions.partnerItemId = flags['partner-item-id'];\n\t\t}\n\t\tif (flags['partner-item-type']) {\n\t\t\toptions.partnerItemType = flags['partner-item-type'];\n\t\t}\n\t\tif (flags['box-item-id']) {\n\t\t\toptions.boxItemId = flags['box-item-id'];\n\t\t}\n\t\tif (flags['box-item-type']) {\n\t\t\toptions.boxItemType = flags['box-item-type'];\n\t\t}\n\n\t\tlet teamsIntegrationMappings =\n\t\t\tawait this.tsClient.integrationMappings.getTeamsIntegrationMapping(\n\t\t\t\toptions\n\t\t\t);\n\t\tawait this.output(\n\t\t\tthis.getOutputContentWithRawJsonSupport(teamsIntegrationMappings)\n\t\t);\n\t}\n}\n\nIntegrationMappingsTeamsListCommand.aliases = [\n\t'integration-mappings:teams:list',\n];\n\nIntegrationMappingsTeamsListCommand.description =\n\t'List Teams integration mappings';\nIntegrationMappingsTeamsListCommand.examples = [\n\t'box integration-mappings:teams --partner-item-id 123 --partner-item-type channel',\n\t'box integration-mappings:teams --box-item-id 456 --box-item-type folder',\n];\nIntegrationMappingsTeamsListCommand._endpoint =\n\t'get_integration_mappings_teams';\n\nIntegrationMappingsTeamsListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n\t...BoxCommand.rawJsonFlags,\n\t'partner-item-id': Flags.string({\n\t\thidden: false,\n\t\tdescription:\n\t\t\t'ID of the mapped item, for which the mapping should be returned',\n\t}),\n\t'partner-item-type': Flags.string({\n\t\thidden: false,\n\t\tdescription:\n\t\t\t'Mapped item type, for which the mapping should be returned, value is one of: channel, team',\n\t}),\n\t'box-item-id': Flags.string({\n\t\thidden: false,\n\t\tdescription: 'Box item ID, for which the mappings should be returned',\n\t}),\n\t'box-item-type': Flags.string({\n\t\thidden: false,\n\t\tdescription:\n\t\t\t'Box item type, for which the mappings should be returned, value is one of: folder',\n\t}),\n};\n\nmodule.exports = IntegrationMappingsTeamsListCommand;\n"
  },
  {
    "path": "src/commands/integration-mappings/teams/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass IntegrationMappingsTeamsUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tIntegrationMappingsTeamsUpdateCommand\n\t\t);\n\t\tlet body = {};\n\n\t\tif (flags['box-item-id']) {\n\t\t\tbody.boxItem = {\n\t\t\t\tid: flags['box-item-id'],\n\t\t\t\ttype: 'folder',\n\t\t\t};\n\t\t}\n\n\t\tlet integrationMapping =\n\t\t\tawait this.tsClient.integrationMappings.updateTeamsIntegrationMappingById(\n\t\t\t\targs.id,\n\t\t\t\t{\n\t\t\t\t\trequestBody: body,\n\t\t\t\t}\n\t\t\t);\n\t\tawait this.output(\n\t\t\tthis.getOutputContentWithRawJsonSupport(integrationMapping)\n\t\t);\n\t}\n}\n\nIntegrationMappingsTeamsUpdateCommand.description =\n\t'Update Teams integration mapping';\nIntegrationMappingsTeamsUpdateCommand.examples = [\n\t'box integration-mappings:teams:update 123 --box-item-id 789',\n];\nIntegrationMappingsTeamsUpdateCommand._endpoint =\n\t'put_integration_mappings_teams_id';\n\nIntegrationMappingsTeamsUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\t...BoxCommand.rawJsonFlags,\n\t'box-item-id': Flags.string({\n\t\tdescription: 'ID of the mapped folder',\n\t}),\n};\n\nIntegrationMappingsTeamsUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of an integration mapping',\n\t}),\n};\n\nmodule.exports = IntegrationMappingsTeamsUpdateCommand;\n"
  },
  {
    "path": "src/commands/legal-hold-policies/assign.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass LegalHoldPoliciesAssignCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tLegalHoldPoliciesAssignCommand\n\t\t);\n\n\t\tlet assignType = flags['assign-to-type'];\n\t\tlet assignID = flags['assign-to-id'];\n\n\t\tlet assignment = await this.client.legalHoldPolicies.assign(\n\t\t\targs.policyID,\n\t\t\tassignType,\n\t\t\tassignID\n\t\t);\n\t\tawait this.output(assignment);\n\t}\n}\n\nLegalHoldPoliciesAssignCommand.description = 'Create a new policy assignment';\nLegalHoldPoliciesAssignCommand.examples = [\n\t'box legal-hold-policies:assign 99999 --assign-to-type folder --assign-to-id 22222',\n];\n\nLegalHoldPoliciesAssignCommand.flags = {\n\t...BoxCommand.flags,\n\t'assign-to-type': Flags.string({\n\t\trequired: true,\n\t\tdescription: 'Type of object to assign the policy to',\n\t\toptions: ['file_version', 'file', 'folder', 'user'],\n\t}),\n\t'assign-to-id': Flags.string({\n\t\tdescription: 'ID of the object to assign the policy to',\n\t\trequired: true,\n\t}),\n};\n\nLegalHoldPoliciesAssignCommand.args = {\n\tpolicyID: Args.string({\n\t\tname: 'policyID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the legal hold policy to assign',\n\t}),\n};\n\nmodule.exports = LegalHoldPoliciesAssignCommand;\n"
  },
  {
    "path": "src/commands/legal-hold-policies/assignments/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass LegalHoldPoliciesDeleteAssignmentCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(\n\t\t\tLegalHoldPoliciesDeleteAssignmentCommand\n\t\t);\n\n\t\tawait this.client.legalHoldPolicies.deleteAssignment(args.id);\n\t\tthis.info(`Delete policy assignment ${args.id}`);\n\t}\n}\n\nLegalHoldPoliciesDeleteAssignmentCommand.description =\n\t'Delete a policy assignment';\nLegalHoldPoliciesDeleteAssignmentCommand.examples = [\n\t'box legal-hold-policies:assignments:delete 99999',\n];\nLegalHoldPoliciesDeleteAssignmentCommand._endpoint =\n\t'delete_legal_hold_policy_assignments_id';\n\nLegalHoldPoliciesDeleteAssignmentCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nLegalHoldPoliciesDeleteAssignmentCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the policy assignment to delete',\n\t}),\n};\n\nmodule.exports = LegalHoldPoliciesDeleteAssignmentCommand;\n"
  },
  {
    "path": "src/commands/legal-hold-policies/assignments/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass LegalHoldPoliciesGetAssignmentCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tLegalHoldPoliciesGetAssignmentCommand\n\t\t);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet assignment = await this.client.legalHoldPolicies.getAssignment(\n\t\t\targs.id,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(assignment);\n\t}\n}\n\nLegalHoldPoliciesGetAssignmentCommand.description =\n\t'Get information about a policy assignment';\nLegalHoldPoliciesGetAssignmentCommand.examples = [\n\t'box legal-hold-policies:assignments:get 99999',\n];\nLegalHoldPoliciesGetAssignmentCommand._endpoint =\n\t'get_legal_hold_policy_assignments_id';\n\nLegalHoldPoliciesGetAssignmentCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nLegalHoldPoliciesGetAssignmentCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the policy assignment to get',\n\t}),\n};\n\nmodule.exports = LegalHoldPoliciesGetAssignmentCommand;\n"
  },
  {
    "path": "src/commands/legal-hold-policies/assignments/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst PaginationUtilities = require('../../../pagination-utils');\n\nclass LegalHoldPoliciesListAssignmentsCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tLegalHoldPoliciesListAssignmentsCommand\n\t\t);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags['assign-to-type']) {\n\t\t\toptions.assign_to_type = flags['assign-to-type'];\n\t\t}\n\t\tif (flags['assign-to-id']) {\n\t\t\toptions.assign_to_id = flags['assign-to-id'];\n\t\t}\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet assignments = await this.client.legalHoldPolicies.getAssignments(\n\t\t\targs.id,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(assignments);\n\t}\n}\n\nLegalHoldPoliciesListAssignmentsCommand.description = 'List policy assignments';\nLegalHoldPoliciesListAssignmentsCommand.examples = [\n\t'box legal-hold-policies:assignments 99999',\n];\nLegalHoldPoliciesListAssignmentsCommand._endpoint =\n\t'get_legal_hold_policy_assignments';\n\nLegalHoldPoliciesListAssignmentsCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n\t'assign-to-type': Flags.string({\n\t\tdescription: 'Filter by assignment type',\n\t\toptions: ['file_version', 'file', 'folder', 'user'],\n\t}),\n\t'assign-to-id': Flags.string({ description: 'Filter by assignment Id' }),\n};\n\nLegalHoldPoliciesListAssignmentsCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the legal hold policy get get assignments for',\n\t}),\n};\n\nmodule.exports = LegalHoldPoliciesListAssignmentsCommand;\n"
  },
  {
    "path": "src/commands/legal-hold-policies/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass LegalHoldPoliciesCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tLegalHoldPoliciesCreateCommand\n\t\t);\n\t\tlet options = {};\n\n\t\tif (flags.description) {\n\t\t\toptions.description = flags.description;\n\t\t}\n\t\tif (flags['filter-started-at']) {\n\t\t\toptions.filter_started_at = flags['filter-started-at'];\n\t\t}\n\t\tif (flags['filter-ended-at']) {\n\t\t\toptions.filter_ended_at = flags['filter-ended-at'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'ongoing')) {\n\t\t\toptions.is_ongoing = true;\n\t\t}\n\n\t\tlet policy = await this.client.legalHoldPolicies.create(\n\t\t\targs.policyName,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(policy);\n\t}\n}\n\nLegalHoldPoliciesCreateCommand.description = 'Create a new legal hold policy';\nLegalHoldPoliciesCreateCommand.examples = [\n\t'box legal-hold-policies:create \"Class Action Suit\" --ongoing',\n];\nLegalHoldPoliciesCreateCommand._endpoint = 'post_legal_hold_policies';\n\nLegalHoldPoliciesCreateCommand.flags = {\n\t...BoxCommand.flags,\n\tdescription: Flags.string({\n\t\tdescription: 'Description of legal hold policy',\n\t\tparse: utilities.unescapeSlashes,\n\t}),\n\t'filter-started-at': Flags.string({\n\t\tdescription:\n\t\t\t\"Date filter applies to Custodian assignments only. Should be today's date or before. Use a RFC3339 timestamp or shorthand syntax 0t, like -5w for 5 weeks ago\",\n\t\tdependsOn: ['filter-ended-at'],\n\t\texclusive: ['is-ongoing'],\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'filter-ended-at': Flags.string({\n\t\tdescription:\n\t\t\t\"Date filter applies to Custodian assignments only. Should be today's date or before. Use a RFC3339 timestamp or shorthand syntax 0t, like -5w for 5 weeks ago\",\n\t\tdependsOn: ['filter-started-at'],\n\t\texclusive: ['is-ongoing'],\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\tongoing: Flags.boolean({\n\t\tdescription:\n\t\t\t'Assignments under this policy will continue applying to files based on events, indefinitely',\n\t\texclusive: ['filter-started-at', 'filter-ended-at'],\n\t}),\n};\n\nLegalHoldPoliciesCreateCommand.args = {\n\tpolicyName: Args.string({\n\t\tname: 'policyName',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Name of the legal hold policy',\n\t}),\n};\n\nmodule.exports = LegalHoldPoliciesCreateCommand;\n"
  },
  {
    "path": "src/commands/legal-hold-policies/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass LegalHoldPoliciesDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(LegalHoldPoliciesDeleteCommand);\n\n\t\tawait this.client.legalHoldPolicies.delete(args.id);\n\t\tthis.info(`Deleted legal hold policy ${args.id}`);\n\t}\n}\n\nLegalHoldPoliciesDeleteCommand.description = 'Delete a legal hold policy';\nLegalHoldPoliciesDeleteCommand.examples = [\n\t'box legal-hold-policies:delete 99999',\n];\nLegalHoldPoliciesDeleteCommand._endpoint = 'delete_legal_hold_policies_id';\n\nLegalHoldPoliciesDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nLegalHoldPoliciesDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the legal hold policy to delete',\n\t}),\n};\n\nmodule.exports = LegalHoldPoliciesDeleteCommand;\n"
  },
  {
    "path": "src/commands/legal-hold-policies/file-version-holds/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass LegalHoldPoliciesGetVersionHoldCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tLegalHoldPoliciesGetVersionHoldCommand\n\t\t);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet fileVersionHold =\n\t\t\tawait this.client.legalHoldPolicies.getFileVersionLegalHold(\n\t\t\t\targs.id,\n\t\t\t\toptions\n\t\t\t);\n\t\tawait this.output(fileVersionHold);\n\t}\n}\n\nLegalHoldPoliciesGetVersionHoldCommand.description =\n\t'Get information about a file version legal hold';\nLegalHoldPoliciesGetVersionHoldCommand.examples = [\n\t'box legal-hold-policies:file-version-holds:get 12345',\n];\nLegalHoldPoliciesGetVersionHoldCommand._endpoint =\n\t'get_file_version_legal_holds_id';\n\nLegalHoldPoliciesGetVersionHoldCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nLegalHoldPoliciesGetVersionHoldCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file version legal hold to get',\n\t}),\n};\n\nmodule.exports = LegalHoldPoliciesGetVersionHoldCommand;\n"
  },
  {
    "path": "src/commands/legal-hold-policies/file-version-holds/index.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\nconst PaginationUtilities = require('../../../pagination-utils');\n\nclass LegalHoldPoliciesListVersionHoldsCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tLegalHoldPoliciesListVersionHoldsCommand\n\t\t);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet fileVersionHolds =\n\t\t\tawait this.client.legalHoldPolicies.getAllFileVersionLegalHolds(\n\t\t\t\targs.id,\n\t\t\t\toptions\n\t\t\t);\n\t\tawait this.output(fileVersionHolds);\n\t}\n}\n\nLegalHoldPoliciesListVersionHoldsCommand.description =\n\t'List file version legal holds for a legal hold policy';\nLegalHoldPoliciesListVersionHoldsCommand.examples = [\n\t'box legal-hold-policies:file-version-holds 99999',\n];\nLegalHoldPoliciesListVersionHoldsCommand._endpoint =\n\t'get_file_version_legal_holds';\n\nLegalHoldPoliciesListVersionHoldsCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nLegalHoldPoliciesListVersionHoldsCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the legal hold policy to get holds for',\n\t}),\n};\n\nmodule.exports = LegalHoldPoliciesListVersionHoldsCommand;\n"
  },
  {
    "path": "src/commands/legal-hold-policies/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass LegalHoldPoliciesGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(LegalHoldPoliciesGetCommand);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet policy = await this.client.legalHoldPolicies.get(args.id, options);\n\t\tawait this.output(policy);\n\t}\n}\n\nLegalHoldPoliciesGetCommand.description =\n\t'Get information about a legal hold policy';\nLegalHoldPoliciesGetCommand.examples = ['box legal-hold-policies:get 99999'];\nLegalHoldPoliciesGetCommand._endpoint = 'get_legal_hold_policies_id';\n\nLegalHoldPoliciesGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nLegalHoldPoliciesGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the legal hold policy to get',\n\t}),\n};\n\nmodule.exports = LegalHoldPoliciesGetCommand;\n"
  },
  {
    "path": "src/commands/legal-hold-policies/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass LegalHoldPoliciesListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(LegalHoldPoliciesListCommand);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags['policy-name']) {\n\t\t\toptions.policy_name = flags['policy-name'];\n\t\t}\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet policies = await this.client.legalHoldPolicies.getAll(options);\n\t\tawait this.output(policies);\n\t}\n}\n\nLegalHoldPoliciesListCommand.description = 'List legal hold policies';\nLegalHoldPoliciesListCommand.examples = ['box legal-hold-policies'];\nLegalHoldPoliciesListCommand._endpoint = 'get_legal_hold_policies';\n\nLegalHoldPoliciesListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n\t'policy-name': Flags.string({ description: 'Filter by policy name' }),\n};\n\nmodule.exports = LegalHoldPoliciesListCommand;\n"
  },
  {
    "path": "src/commands/legal-hold-policies/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass LegalHoldPoliciesUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tLegalHoldPoliciesUpdateCommand\n\t\t);\n\t\tlet updates = {};\n\n\t\tif (flags.description) {\n\t\t\tupdates.description = flags.description;\n\t\t}\n\t\tif (flags['policy-name']) {\n\t\t\tupdates.policy_name = flags['policy-name'];\n\t\t}\n\t\tif (flags['release-notes']) {\n\t\t\tupdates.release_notes = flags['release-notes'];\n\t\t}\n\n\t\tlet policy = await this.client.legalHoldPolicies.update(\n\t\t\targs.id,\n\t\t\tupdates\n\t\t);\n\t\tawait this.output(policy);\n\t}\n}\n\nLegalHoldPoliciesUpdateCommand.description = 'Update a legal hold policy';\nLegalHoldPoliciesUpdateCommand.examples = [\n\t'box legal-hold-policies:update 99999 --description \"Files related to the ongoing class action suit\"',\n];\nLegalHoldPoliciesUpdateCommand._endpoint = 'put_legal_hold_policies_id';\n\nLegalHoldPoliciesUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\tdescription: Flags.string({\n\t\tdescription: 'Description of legal hold policy. Max characters 500',\n\t\tparse: utilities.unescapeSlashes,\n\t}),\n\t'policy-name': Flags.string({\n\t\tdescription: 'Name of legal hold policy. Max characters 254',\n\t}),\n\t'release-notes': Flags.string({\n\t\tdescription:\n\t\t\t'Notes around why the policy was released. Max characters 500',\n\t}),\n};\n\nLegalHoldPoliciesUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of a legal hold policy to update',\n\t}),\n};\n\nmodule.exports = LegalHoldPoliciesUpdateCommand;\n"
  },
  {
    "path": "src/commands/login.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../box-command');\nconst { Flags } = require('@oclif/core');\nconst fs = require('node:fs');\nconst BoxSDK = require('box-node-sdk').default;\nconst BoxCLIError = require('../cli-error');\nconst CLITokenCache = require('../token-cache');\nconst package_ = require('../../package.json');\nconst chalk = require('chalk');\nconst express = require('express');\nconst inquirer = require('../inquirer');\nconst path = require('node:path');\nconst ora = require('ora');\nconst http = require('node:http');\nconst { nanoid } = require('nanoid');\nconst DEBUG = require('../debug');\nconst { generatePKCE } = require('../pkce-support');\nconst {\n\tassertValidOAuthCode,\n\tgetTokenInfoByAuthCode,\n} = require('../login-helper');\n\nconst GENERIC_OAUTH_CLIENT_ID = 'udz8zp4yue87uk9dzq4xk425kkwvqvh1';\nconst GENERIC_OAUTH_CLIENT_SECRET = 'iZ1MbvC3ZaF25nbJli7IsKdRHAxfu3fn';\nconst SUPPORTED_DEFAULT_APP_PORTS = [3000, 3001, 4000, 5000, 8080];\nconst DEFAULT_ENVIRONMENT_NAME = 'oauth';\nconst OAUTH_CALLBACK_TIMEOUT_MS = 5 * 60 * 1000;\nconst LOOPBACK_HOST = 'localhost';\nconst DEFAULT_OPEN_AUTHORIZE_IN_BROWSER = (\n\topenFn,\n\tapps,\n\tauthorizeUrl,\n\tuseIncognito\n) => {\n\tif (useIncognito) {\n\t\topenFn(authorizeUrl, {\n\t\t\tnewInstance: true,\n\t\t\tapp: { name: apps.browserPrivate },\n\t\t});\n\t} else {\n\t\topenFn(authorizeUrl);\n\t}\n};\n\nlet oauthCallbackTimeoutMs = OAUTH_CALLBACK_TIMEOUT_MS;\nlet openAuthorizeInBrowser = DEFAULT_OPEN_AUTHORIZE_IN_BROWSER;\n\nasync function promptForPlatformAppCredentials(inquirerModule, clientId) {\n\tif (!clientId) {\n\t\tconst answer = await inquirerModule.prompt([\n\t\t\t{\n\t\t\t\ttype: 'input',\n\t\t\t\tname: 'clientId',\n\t\t\t\tmessage: 'Enter the Client ID:',\n\t\t\t},\n\t\t]);\n\t\tclientId = answer.clientId.trim();\n\t}\n\n\tconst { clientSecret } = await inquirerModule.prompt([\n\t\t{\n\t\t\ttype: 'input',\n\t\t\tname: 'clientSecret',\n\t\t\tmessage: 'Enter the Client Secret:',\n\t\t},\n\t]);\n\n\treturn {\n\t\tuseDefaultBoxApp: false,\n\t\tclientId,\n\t\tclientSecret,\n\t};\n}\n\nasync function promptForAuthMethod(inquirerModule) {\n\tconst CLIENT_ID_MIN_LENGTH = 16;\n\tconst CLIENT_ID_MAX_LENGTH = 99;\n\n\twhile (true) {\n\t\tconst { choice } = await inquirerModule.prompt([\n\t\t\t{\n\t\t\t\ttype: 'input',\n\t\t\t\tname: 'choice',\n\t\t\t\tmessage:\n\t\t\t\t\t'How would you like to authenticate?\\n[1] Log-in as a Box user (OAuth)\\n[2] Use a Box Platform App\\n[q] Quit\\n? Enter 1, 2, or q:',\n\t\t\t},\n\t\t]);\n\n\t\tconst trimmedChoice = typeof choice === 'string' ? choice.trim() : '';\n\n\t\tif (trimmedChoice === '1') {\n\t\t\treturn {\n\t\t\t\tuseDefaultBoxApp: true,\n\t\t\t\tclientId: GENERIC_OAUTH_CLIENT_ID,\n\t\t\t\tclientSecret: GENERIC_OAUTH_CLIENT_SECRET,\n\t\t\t};\n\t\t}\n\n\t\tif (trimmedChoice === '2') {\n\t\t\treturn promptForPlatformAppCredentials(inquirerModule);\n\t\t}\n\n\t\tif (trimmedChoice.toLowerCase() === 'q') {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (\n\t\t\ttrimmedChoice.length > CLIENT_ID_MIN_LENGTH &&\n\t\t\ttrimmedChoice.length < CLIENT_ID_MAX_LENGTH\n\t\t) {\n\t\t\treturn promptForPlatformAppCredentials(\n\t\t\t\tinquirerModule,\n\t\t\t\ttrimmedChoice\n\t\t\t);\n\t\t}\n\n\t\t// Invalid input — repeat the prompt\n\t}\n}\n\nclass OAuthLoginCommand extends BoxCommand {\n\tasync run() {\n\t\tconst openModule = await import('open');\n\t\tconst open = openModule.default;\n\t\tconst apps = openModule.apps;\n\n\t\tconst { flags } = await this.parse(OAuthLoginCommand);\n\t\tconst forceDefaultBoxApp = flags['default-box-app'];\n\t\tconst forcePlatformApp = flags['platform-app'];\n\t\tlet useDefaultBoxApp = false;\n\t\tconst environmentsObject = await this.getEnvironments();\n\t\tconst port = flags.port;\n\t\tconst redirectUri = `http://${LOOPBACK_HOST}:${port}/callback`;\n\t\tconst isUnsupportedDefaultAppPort = () =>\n\t\t\tuseDefaultBoxApp && !SUPPORTED_DEFAULT_APP_PORTS.includes(port);\n\t\tlet environment;\n\n\t\tif (this.flags.reauthorize) {\n\t\t\tlet targetEnvName = this.flags.name;\n\t\t\tif (\n\t\t\t\t!Object.hasOwn(environmentsObject.environments, this.flags.name)\n\t\t\t) {\n\t\t\t\tconst currentEnv =\n\t\t\t\t\tenvironmentsObject.environments[environmentsObject.default];\n\t\t\t\tif (\n\t\t\t\t\tthis.flags.name === DEFAULT_ENVIRONMENT_NAME &&\n\t\t\t\t\tenvironmentsObject.default &&\n\t\t\t\t\tcurrentEnv?.authMethod === 'oauth20'\n\t\t\t\t) {\n\t\t\t\t\ttargetEnvName = environmentsObject.default;\n\t\t\t\t} else {\n\t\t\t\t\tthis.info(\n\t\t\t\t\t\tchalk`{red The \"${this.flags.name}\" environment does not exist}`\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tenvironment = environmentsObject.environments[targetEnvName];\n\t\t\tif (environment.authMethod !== 'oauth20') {\n\t\t\t\tthis.info(\n\t\t\t\t\tchalk`{red The selected environment is not of type oauth20}`\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (forceDefaultBoxApp) {\n\t\t\t\tuseDefaultBoxApp = true;\n\t\t\t\tenvironment.clientId = GENERIC_OAUTH_CLIENT_ID;\n\t\t\t\tenvironment.clientSecret = GENERIC_OAUTH_CLIENT_SECRET;\n\t\t\t} else {\n\t\t\t\tuseDefaultBoxApp =\n\t\t\t\t\tenvironment.clientId === GENERIC_OAUTH_CLIENT_ID &&\n\t\t\t\t\tenvironment.clientSecret === GENERIC_OAUTH_CLIENT_SECRET;\n\t\t\t}\n\t\t} else {\n\t\t\tuseDefaultBoxApp = forceDefaultBoxApp;\n\t\t}\n\n\t\tif (this.flags.reauthorize) {\n\t\t\t// Keep the selected existing environment config for reauthorization.\n\t\t} else if (useDefaultBoxApp) {\n\t\t\tthis.info(chalk`{cyan ----------------------------------------}`);\n\t\t\tthis.info(\n\t\t\t\tchalk`{cyan No app setup is required in Box Developer Console.}`\n\t\t\t);\n\t\t\tthis.info(chalk`{cyan Callback URL: {italic ${redirectUri}}}`);\n\t\t\tthis.info(\n\t\t\t\tchalk`{cyan Supported callback ports for this flow: {bold 3000}, {bold 3001}, {bold 4000}, {bold 5000}, {bold 8080}.}`\n\t\t\t);\n\t\t\tthis.info(\n\t\t\t\tchalk`{cyan You can change the port with {bold --port}, but only to one of the supported values above.}`\n\t\t\t);\n\t\t\tthis.info(chalk`{cyan ----------------------------------------}`);\n\n\t\t\tenvironment = {\n\t\t\t\tclientId: GENERIC_OAUTH_CLIENT_ID,\n\t\t\t\tclientSecret: GENERIC_OAUTH_CLIENT_SECRET,\n\t\t\t\tname: this.flags.name,\n\t\t\t\tcacheTokens: true,\n\t\t\t\tauthMethod: 'oauth20',\n\t\t\t};\n\t\t} else if (forcePlatformApp) {\n\t\t\tconst answers = await promptForPlatformAppCredentials(inquirer);\n\t\t\tuseDefaultBoxApp = false;\n\n\t\t\tenvironment = {\n\t\t\t\tclientId: answers.clientId,\n\t\t\t\tclientSecret: answers.clientSecret,\n\t\t\t\tname: this.flags.name,\n\t\t\t\tcacheTokens: true,\n\t\t\t\tauthMethod: 'oauth20',\n\t\t\t};\n\t\t} else {\n\t\t\tconst answers = await promptForAuthMethod(inquirer);\n\t\t\tif (answers === null) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tuseDefaultBoxApp = answers.useDefaultBoxApp;\n\n\t\t\tenvironment = {\n\t\t\t\tclientId: answers.clientId,\n\t\t\t\tclientSecret: answers.clientSecret,\n\t\t\t\tname: this.flags.name,\n\t\t\t\tcacheTokens: true,\n\t\t\t\tauthMethod: 'oauth20',\n\t\t\t};\n\t\t}\n\n\t\tif (isUnsupportedDefaultAppPort()) {\n\t\t\tthis.info(\n\t\t\t\tchalk`{red Unsupported port \"${port}\" for the Official Box CLI app flow. Supported ports: ${SUPPORTED_DEFAULT_APP_PORTS.join(', ')}}`\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tconst environmentName = environment.name;\n\t\tconst sdkConfig = Object.freeze({\n\t\t\tanalyticsClient: {\n\t\t\t\tversion: package_.version,\n\t\t\t},\n\t\t});\n\t\tconst sdk = new BoxSDK({\n\t\t\tclientID: environment.clientId,\n\t\t\tclientSecret: environment.clientSecret,\n\t\t});\n\t\tthis._configureSdk(sdk, sdkConfig);\n\n\t\tconst app = express();\n\t\tlet callbackHandled = false;\n\n\t\t// Keep run() blocked until callback flow completes.\n\t\t// This prevents command exit before the OAuth redirect returns.\n\t\tlet resolveCallbackFlow;\n\t\tconst callbackFlowDone = new Promise((resolve) => {\n\t\t\tresolveCallbackFlow = resolve;\n\t\t});\n\t\tlet callbackTimeout;\n\n\t\t// Timeout and callback may race, so teardown must be idempotent.\n\t\t// This guard ensures cleanup and resolve happen only once.\n\t\tlet callbackFlowResolved = false;\n\n\t\tlet server;\n\t\ttry {\n\t\t\t// Bind only to loopback to avoid exposing callback externally.\n\t\t\t// Browser redirect is local, so external interfaces are unnecessary.\n\t\t\tserver = await new Promise((resolve, reject) => {\n\t\t\t\tconst s = app.listen(port, LOOPBACK_HOST);\n\t\t\t\ts.once('listening', () => resolve(s));\n\t\t\t\ts.once('error', reject);\n\t\t\t});\n\t\t} catch (error) {\n\t\t\tif (error.code === 'EADDRINUSE') {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t`Port ${port} is already in use. Please close the application using this port or use --port to specify a different port.`,\n\t\t\t\t\terror\n\t\t\t\t);\n\t\t\t}\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t`Failed to start local OAuth server on port ${port}: ${error.message}`,\n\t\t\t\terror\n\t\t\t);\n\t\t}\n\n\t\tconst shutdownServer = () => {\n\t\t\tif (!server) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tserver.close();\n\t\t\tif (typeof server.closeAllConnections === 'function') {\n\t\t\t\tserver.closeAllConnections();\n\t\t\t}\n\t\t};\n\n\t\t// Use one finalize path so all exits apply the same cleanup.\n\t\t// This keeps timeout and callback completion behavior consistent.\n\t\tconst finalizeCallbackFlow = () => {\n\t\t\tif (callbackFlowResolved) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tcallbackFlowResolved = true;\n\t\t\tclearTimeout(callbackTimeout);\n\t\t\tshutdownServer();\n\t\t\tresolveCallbackFlow();\n\t\t};\n\n\t\t// Bound callback wait time to avoid hanging sessions forever.\n\t\t// If user abandons auth, the command exits predictably.\n\t\tcallbackTimeout = setTimeout(() => {\n\t\t\tif (callbackHandled) {\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tthis.info(\n\t\t\t\tchalk`{red Login timed out waiting for OAuth callback after ${oauthCallbackTimeoutMs / 1000} seconds.}`\n\t\t\t);\n\t\t\tfinalizeCallbackFlow();\n\t\t}, oauthCallbackTimeoutMs);\n\n\t\tconst state = nanoid(32);\n\t\tconst pkce = useDefaultBoxApp ? generatePKCE() : null;\n\n\t\tapp.get('/callback', async (request, res) => {\n\t\t\t// Reject replayed callbacks after a completion was already accepted.\n\t\t\t// This enforces single-use semantics for the local callback endpoint.\n\t\t\tif (callbackHandled) {\n\t\t\t\tres.status(409).send('OAuth callback already handled.');\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tcallbackHandled = true;\n\n\t\t\ttry {\n\t\t\t\tif (request.query.state !== state) {\n\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t`Invalid OAuth state received in callback. Got \"${request.query.state}\" while expecting \"${state}\"`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tassertValidOAuthCode(request.query.code);\n\t\t\t\tconst tokenInfo = await getTokenInfoByAuthCode(\n\t\t\t\t\tsdk,\n\t\t\t\t\trequest.query.code,\n\t\t\t\t\tredirectUri,\n\t\t\t\t\tpkce?.codeVerifier\n\t\t\t\t);\n\t\t\t\tconst tokenCache = new CLITokenCache(environmentName);\n\t\t\t\tawait new Promise((resolve, reject) => {\n\t\t\t\t\ttokenCache.write(tokenInfo, (error) => {\n\t\t\t\t\t\tif (error) {\n\t\t\t\t\t\t\treject(error);\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tresolve();\n\t\t\t\t\t\t}\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t\tconst client = sdk.getPersistentClient(tokenInfo, tokenCache);\n\t\t\t\tconst user = await client.users.get('me');\n\n\t\t\t\tenvironmentsObject.environments[environmentName] = environment;\n\t\t\t\tenvironmentsObject.default = environmentName;\n\t\t\t\tawait this.updateEnvironments(environmentsObject);\n\n\t\t\t\tconst callbackHtmlPath = path.resolve(\n\t\t\t\t\t__dirname,\n\t\t\t\t\t'../logged-in.html'\n\t\t\t\t);\n\n\t\t\t\tlet html = fs.readFileSync(callbackHtmlPath, 'utf8');\n\t\t\t\thtml = html.replace('example@box.com', user.login);\n\t\t\t\tres.send(html);\n\n\t\t\t\tthis.info(\n\t\t\t\t\tchalk`{green Successfully logged in as ${user.login}!}`\n\t\t\t\t);\n\t\t\t\tif (this.flags.reauthorize) {\n\t\t\t\t\tthis.info(\n\t\t\t\t\t\tchalk`{green Environment \"${environmentName}\" has been updated, selected and it's ready to use.}`\n\t\t\t\t\t);\n\t\t\t\t} else {\n\t\t\t\t\tthis.info(\n\t\t\t\t\t\tchalk`{green New environment \"${environmentName}\" has been created and selected.}`\n\t\t\t\t\t);\n\t\t\t\t\tthis.info(\n\t\t\t\t\t\tchalk`{green You are set up to make your first API call. Refer to the CLI commands library (https://github.com/box/boxcli#command-topics) for examples.}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconst statusCode =\n\t\t\t\t\terror?.response?.statusCode ?? error?.response?.status;\n\t\t\t\tconst errorMessage =\n\t\t\t\t\terror?.response?.body?.error_description ||\n\t\t\t\t\t(statusCode\n\t\t\t\t\t\t? `Request failed with status ${statusCode}`\n\t\t\t\t\t\t: null) ||\n\t\t\t\t\terror?.message ||\n\t\t\t\t\t'Unknown error';\n\t\t\t\tDEBUG.execute('Login error: %O', error);\n\t\t\t\tthis.info(chalk`{red Login failed: ${errorMessage}}`);\n\t\t\t\tres.status(500).send('Login failed. Please check the CLI output for details.');\n\n\t\t\t} finally {\n\t\t\t\tfinalizeCallbackFlow();\n\t\t\t}\n\t\t});\n\n\t\tconst spinner = ora({\n\t\t\ttext: chalk`{bgCyan Opening browser for OAuth authentication. Please click {bold Grant access to Box} to continue.}`,\n\t\t\tspinner: 'bouncingBall',\n\t\t}).start();\n\n\t\tawait new Promise((resolve) => setTimeout(resolve, 1000));\n\n\t\tspinner.succeed();\n\n\t\t// the URL to redirect the user to\n\t\tconst authorizeUrl = sdk.getAuthorizeURL({\n\t\t\tresponse_type: 'code',\n\t\t\tstate,\n\t\t\tredirect_uri: redirectUri,\n\t\t\t...(useDefaultBoxApp\n\t\t\t\t? {\n\t\t\t\t\t\tcode_challenge: pkce.codeChallenge,\n\t\t\t\t\t}\n\t\t\t\t: {}),\n\t\t});\n\t\tif (flags.code) {\n\t\t\tthis.info(\n\t\t\t\tchalk`{green Please open ${authorizeUrl} to authorize the application and read parameters from the URL accessed after authorization.}`\n\t\t\t);\n\t\t\tthis.info(\n\t\t\t\tchalk`{yellow If you are not seeing your code, please make sure you have set up the Redirect URI.}`\n\t\t\t);\n\t\t\tconst authInfo = await inquirer.prompt([\n\t\t\t\t{\n\t\t\t\t\ttype: 'input',\n\t\t\t\t\tname: 'code',\n\t\t\t\t\tmessage: 'What is your auth code? (code=)',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'input',\n\t\t\t\t\tname: 'state',\n\t\t\t\t\tmessage: 'What is your state code? (state=)',\n\t\t\t\t},\n\t\t\t]);\n\t\t\thttp.get(\n\t\t\t\t`http://${LOOPBACK_HOST}:${port}/callback?state=${authInfo.state}&code=${authInfo.code}`\n\t\t\t);\n\t\t} else {\n\t\t\topenAuthorizeInBrowser(\n\t\t\t\topen,\n\t\t\t\tapps,\n\t\t\t\tauthorizeUrl,\n\t\t\t\tflags['incognito-browser']\n\t\t\t);\n\t\t\tthis.info(\n\t\t\t\tuseDefaultBoxApp\n\t\t\t\t\t? chalk`{yellow If authorization fails, verify that you are using one of the supported ports for the Official Box CLI app flow and restart the login command.}`\n\t\t\t\t\t: chalk`{yellow If you are redirected to the Files view, make sure your Redirect URI is configured correctly and restart the login command.}`\n\t\t\t);\n\t\t}\n\t\tawait callbackFlowDone;\n\t}\n}\n\n// @NOTE: This command MUST skip client setup, since it is used to add the first environment\nOAuthLoginCommand.noClient = true;\n\nOAuthLoginCommand.description =\n\t'Sign in with OAuth 2.0 and create a new environment (or update an existing one with --reauthorize).\\n' +\n\t'\\n' +\n\t'Login options:\\n' +\n\t'\\n' +\n\t'  (1) Official Box CLI App\\n' +\n\t'      No app setup needed. Use --default-box-app (-d) to skip the prompt.\\n' +\n\t'\\n' +\n\t'  (2) Your own Platform OAuth App\\n' +\n\t'      Enter your Client ID and Client Secret when prompted. Use --platform-app to skip the prompt.\\n' +\n\t'\\n' +\n\t'Quickstart: run \"box login -d\" to sign in immediately. A browser window will open for authorization. Once access is granted, the environment is created and set as default — you can start running commands right away.\\n' +\n\t'\\n' +\n\t'Headless environments: use --code (-c) if no browser is available. The CLI will display an authorize URL — visit it in an external browser, authorize and grant access to the app, then provide the state and authorization code back to the CLI when prompted.';\n\nOAuthLoginCommand.flags = {\n\t...BoxCommand.minFlags,\n\tcode: Flags.boolean({\n\t\tchar: 'c',\n\t\tdescription: 'Manually provide state and authorization code instead of using a local callback server. Use this in headless environments where no browser is available — the CLI will display an authorize URL to visit externally.',\n\t\tdefault: false,\n\t}),\n\tname: Flags.string({\n\t\tchar: 'n',\n\t\tdescription: 'Set a name for the environment',\n\t\tdefault: DEFAULT_ENVIRONMENT_NAME,\n\t}),\n\tport: Flags.integer({\n\t\tchar: 'p',\n\t\tdescription: 'Set the port number for the local OAuth callback server',\n\t\tdefault: 3000,\n\t}),\n\t'default-box-app': Flags.boolean({\n\t\tchar: 'd',\n\t\tdescription:\n\t\t\t'Use the Official Box CLI app flow and proceed directly to authorization.\\n' +\n\t\t\t'This is the fastest way to integrate with Box — no app creation in the Developer Console is needed.\\n' +\n\t\t\t'Scopes are limited to content actions, allowing you to effectively operate with your files and folders.\\n' +\n\t\t\t'This flow requires a local callback server on a supported port (3000, 3001, 4000, 5000, or 8080). The default port is 3000; use --port to change it.',\n\t\texclusive: ['platform-app'],\n\t\tdefault: false,\n\t}),\n\t'platform-app': Flags.boolean({\n\t\tdescription:\n\t\t\t'Skip the authentication method prompt and go directly to Platform App setup.\\n' +\n\t\t\t'You will be prompted for Client ID and Client Secret.',\n\t\texclusive: ['default-box-app'],\n\t\tdefault: false,\n\t}),\n\treauthorize: Flags.boolean({\n\t\tchar: 'r',\n\t\tdescription: 'Reauthorize the existing environment with given `name`',\n\t\tdependsOn: ['name'],\n\t\tdefault: false,\n\t}),\n\t'incognito-browser': Flags.boolean({\n\t\tchar: 'i',\n\t\tdescription: 'Visit authorize URL with incognito browser',\n\t\tdefault: false,\n\t}),\n};\n\nmodule.exports = OAuthLoginCommand;\nmodule.exports._test = {\n\tpromptForAuthMethod,\n\tpromptForPlatformAppCredentials,\n\tsetOAuthCallbackTimeoutMs(timeoutMs) {\n\t\toauthCallbackTimeoutMs = timeoutMs;\n\t},\n\tresetOAuthCallbackTimeoutMs() {\n\t\toauthCallbackTimeoutMs = OAUTH_CALLBACK_TIMEOUT_MS;\n\t},\n\tsetOpenAuthorizeInBrowser(fn) {\n\t\topenAuthorizeInBrowser = fn;\n\t},\n\tresetOpenAuthorizeInBrowser() {\n\t\topenAuthorizeInBrowser = DEFAULT_OPEN_AUTHORIZE_IN_BROWSER;\n\t},\n};\n"
  },
  {
    "path": "src/commands/logout.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../box-command');\nconst BoxSDK = require('box-node-sdk').default;\nconst CLITokenCache = require('../token-cache');\nconst chalk = require('chalk');\nconst inquirer = require('../inquirer');\nconst pkg = require('../../package.json');\nconst { Flags } = require('@oclif/core');\n\nconst SDK_CONFIG = Object.freeze({\n\tanalyticsClient: { version: pkg.version },\n\trequest: {\n\t\theaders: { 'User-Agent': `Box CLI v${pkg.version}` },\n\t},\n});\n\nfunction isInvalidTokenResponse(response) {\n\treturn (\n\t\tresponse?.statusCode === 400 &&\n\t\tresponse?.body?.error === 'invalid_token'\n\t);\n}\n\nfunction isSuccessResponse(response) {\n\treturn response?.statusCode === 200;\n}\n\nfunction getRevokeErrorMessage(thrownError, response) {\n\tif (thrownError) {\n\t\treturn (\n\t\t\tthrownError.message ||\n\t\t\t'Unexpected error. Cannot connect to Box servers.'\n\t\t);\n\t}\n\treturn (\n\t\tresponse?.body?.error_description ||\n\t\t`Request failed with status ${response?.statusCode ?? response?.status}` ||\n\t\t'Unknown error'\n\t);\n}\n\nclass OAuthLogoutCommand extends BoxCommand {\n\tasync run() {\n\t\tconst environmentsObj = await this.getEnvironments();\n\t\tconst currentEnv = environmentsObj?.default;\n\n\t\tconst environment = currentEnv\n\t\t\t? environmentsObj.environments[currentEnv]\n\t\t\t: null;\n\n\t\tif (!currentEnv || !environment) {\n\t\t\tthis.error(\n\t\t\t\t'No current environment found. Nothing to log out from.'\n\t\t\t);\n\t\t}\n\n\t\tconst tokenCache = new CLITokenCache(currentEnv);\n\t\tconst tokenInfo = await tokenCache.get();\n\t\tconst accessToken = tokenInfo?.accessToken;\n\t\tif (!accessToken) {\n\t\t\tthis.info(\n\t\t\t\tchalk`{green You are already logged out from \"${currentEnv}\" environment.}`\n\t\t\t);\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this.flags.force) {\n\t\t\tconst confirmed = await this.confirm(\n\t\t\t\t`Do you want to logout from \"${currentEnv}\" environment?`,\n\t\t\t\tfalse\n\t\t\t);\n\t\t\tif (!confirmed) {\n\t\t\t\tthis.info(chalk`{yellow Logout cancelled.}`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t}\n\n\t\tawait this.revokeAndClearSession(\n\t\t\taccessToken,\n\t\t\ttokenCache,\n\t\t\tcurrentEnv,\n\t\t\tenvironment\n\t\t);\n\t}\n\n\tasync revokeAndClearSession(\n\t\taccessToken,\n\t\ttokenCache,\n\t\tcurrentEnv,\n\t\tenvironment\n\t) {\n\t\twhile (true) {\n\t\t\tlet response;\n\t\t\tlet thrownError;\n\t\t\tconst { clientId, clientSecret } =\n\t\t\t\tthis.getClientCredentials(environment);\n\t\t\tif (!clientId || !clientSecret) {\n\t\t\t\tthrownError = new Error('Invalid client credentials.');\n\t\t\t\tresponse = undefined;\n\t\t\t} else {\n\t\t\t\tconst sdk = new BoxSDK({\n\t\t\t\t\tclientID: clientId,\n\t\t\t\t\tclientSecret,\n\t\t\t\t\t...SDK_CONFIG,\n\t\t\t\t});\n\t\t\t\ttry {\n\t\t\t\t\tresponse = await sdk.revokeTokens(accessToken);\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthrownError = error;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (isSuccessResponse(response)) {\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tif (isInvalidTokenResponse(response)) {\n\t\t\t\tthis.info(\n\t\t\t\t\tchalk`{yellow Access token is already invalid. Clearing local session.}`\n\t\t\t\t);\n\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\tconst action = await this.promptRevokeFailureAction(\n\t\t\t\tthrownError,\n\t\t\t\tresponse\n\t\t\t);\n\n\t\t\tif (action === 'abort') {\n\t\t\t\tthis.info(\n\t\t\t\t\tchalk`{yellow Logout aborted. Token was not revoked and remains cached.}`\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (action === 'clear') {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tawait new Promise((resolve, reject) => {\n\t\t\ttokenCache.clear((err) => (err ? reject(err) : resolve()));\n\t\t});\n\t\tthis.info(\n\t\t\tchalk`{green Successfully logged out from \"${currentEnv}\" environment.}`\n\t\t);\n\t}\n\n\tgetClientCredentials(environment) {\n\t\tif (environment.boxConfigFilePath) {\n\t\t\ttry {\n\t\t\t\tconst fs = require('node:fs');\n\t\t\t\tconst configObj = JSON.parse(\n\t\t\t\t\tfs.readFileSync(environment.boxConfigFilePath)\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tclientId: configObj?.boxAppSettings?.clientID ?? '',\n\t\t\t\t\tclientSecret: configObj?.boxAppSettings?.clientSecret ?? '',\n\t\t\t\t};\n\t\t\t} catch {\n\t\t\t\t// fall through to environment\n\t\t\t}\n\t\t}\n\t\treturn {\n\t\t\tclientId: environment.clientId ?? '',\n\t\t\tclientSecret: environment.clientSecret ?? '',\n\t\t};\n\t}\n\n\tasync promptRevokeFailureAction(thrownError, response) {\n\t\tconst onRevokeFailure = this.flags['on-revoke-failure'];\n\t\tif (onRevokeFailure) {\n\t\t\treturn onRevokeFailure;\n\t\t}\n\t\tconst result = await inquirer.prompt([\n\t\t\t{\n\t\t\t\ttype: 'list',\n\t\t\t\tname: 'action',\n\t\t\t\tmessage: chalk`Could not revoke token: {red ${getRevokeErrorMessage(thrownError, response)}}\\nWhat would you like to do?`,\n\t\t\t\tchoices: [\n\t\t\t\t\t{ name: 'Try revoking again', value: 'retry' },\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'Clear local session only (token remains valid on Box)',\n\t\t\t\t\t\tvalue: 'clear',\n\t\t\t\t\t},\n\t\t\t\t\t{ name: 'Abort', value: 'abort' },\n\t\t\t\t],\n\t\t\t},\n\t\t]);\n\t\treturn result.action;\n\t}\n}\n\n// @NOTE: This command skips client setup, since it may be used when token is expired\nOAuthLogoutCommand.noClient = true;\n\nOAuthLogoutCommand.description = [\n\t'Revoke the access token and clear local token cache.',\n\t'',\n\t'For OAuth, run `box login` to authorize again.',\n\t'For CCG and JWT, a new token is fetched automatically on the next command.',\n\t'',\n\t'Use -f and --on-revoke-failure=clear or --on-revoke-failure=abort to skip the interactive prompt.',\n].join('\\n');\n\nOAuthLogoutCommand.flags = {\n\t...BoxCommand.minFlags,\n\tforce: Flags.boolean({\n\t\tchar: 'f',\n\t\tdescription: 'Skip confirmation prompt',\n\t}),\n\t'on-revoke-failure': Flags.string({\n\t\tdescription:\n\t\t\t'On revoke failure: \"clear\" clears local cache only, \"abort\" exits without clearing. Skips prompt.',\n\t\toptions: ['clear', 'abort'],\n\t}),\n};\n\nmodule.exports = OAuthLogoutCommand;\n"
  },
  {
    "path": "src/commands/metadata-cascade-policies/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\nconst chalk = require('chalk');\n\nclass MetadataCascadePoliciesDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(MetadataCascadePoliciesDeleteCommand);\n\n\t\tawait this.client.metadata.deleteCascadePolicy(args.id);\n\t\tthis.info(chalk`{green Successfully deleted policy ${args.id}}`);\n\t}\n}\n\nMetadataCascadePoliciesDeleteCommand.description =\n\t'Delete a metadata cascade policy';\nMetadataCascadePoliciesDeleteCommand.examples = [\n\t'box metadata-cascade-policies:delete 12345',\n];\nMetadataCascadePoliciesDeleteCommand._endpoint =\n\t'delete_metadata_cascade_policies_id';\n\nMetadataCascadePoliciesDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nMetadataCascadePoliciesDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The ID of the metadata cascade policy to delete',\n\t}),\n};\n\nmodule.exports = MetadataCascadePoliciesDeleteCommand;\n"
  },
  {
    "path": "src/commands/metadata-cascade-policies/force-apply.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst chalk = require('chalk');\n\nclass MetadataCascadePoliciesForceApplyCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tMetadataCascadePoliciesForceApplyCommand\n\t\t);\n\n\t\tawait this.client.metadata.forceApplyCascadePolicy(\n\t\t\targs.id,\n\t\t\tflags['conflict-resolution']\n\t\t);\n\t\tthis.info(chalk`{green Successfully applied policy ${args.id}}`);\n\t}\n}\n\nMetadataCascadePoliciesForceApplyCommand.description =\n\t'Force apply a cascade policy to the existing items in a folder';\nMetadataCascadePoliciesForceApplyCommand.examples = [\n\t'box metadata-cascade-policies:force-apply 12345 --conflict-resolution overwrite',\n];\nMetadataCascadePoliciesForceApplyCommand._endpoint =\n\t'post_metadata_cascade_policies_apply';\n\nMetadataCascadePoliciesForceApplyCommand.flags = {\n\t...BoxCommand.flags,\n\t'conflict-resolution': Flags.string({\n\t\tdescription:\n\t\t\t'The way to resolve conflicts with the metadata being applied',\n\t\trequired: true,\n\t\toptions: ['none', 'overwrite'],\n\t}),\n};\n\nMetadataCascadePoliciesForceApplyCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The ID of the cascade policy to force apply',\n\t}),\n};\n\nmodule.exports = MetadataCascadePoliciesForceApplyCommand;\n"
  },
  {
    "path": "src/commands/metadata-cascade-policies/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass MetadataCascadePoliciesGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(MetadataCascadePoliciesGetCommand);\n\n\t\tlet policy = await this.client.metadata.getCascadePolicy(args.id);\n\t\tawait this.output(policy);\n\t}\n}\n\nMetadataCascadePoliciesGetCommand.description =\n\t'Get information about a metadata cascade policy';\nMetadataCascadePoliciesGetCommand.examples = [\n\t'box metadata-cascade-policies:get 12345',\n];\nMetadataCascadePoliciesGetCommand._endpoint =\n\t'get_metadata_cascade_policies_id';\n\nMetadataCascadePoliciesGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nMetadataCascadePoliciesGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The ID of the cascade policy to get',\n\t}),\n};\n\nmodule.exports = MetadataCascadePoliciesGetCommand;\n"
  },
  {
    "path": "src/commands/metadata-cascade-policies/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass MetadataCascadePoliciesListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tMetadataCascadePoliciesListCommand\n\t\t);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags['owner-enterprise-id']) {\n\t\t\toptions.owner_enterprise_id = flags['owner-enterprise-id'];\n\t\t}\n\n\t\tlet policies = await this.client.metadata.getCascadePolicies(\n\t\t\targs.folderID,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(policies);\n\t}\n}\n\nMetadataCascadePoliciesListCommand.description =\n\t'List the metadata cascade policies on a folder';\nMetadataCascadePoliciesListCommand.examples = [\n\t'box metadata-cascade-policies 22222',\n];\nMetadataCascadePoliciesListCommand._endpoint = 'get_metadata_cascade_policies';\n\nMetadataCascadePoliciesListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n\t'owner-enterprise-id': Flags.string({\n\t\tdescription: 'The ID of the enterprise to filter cascade policies for ',\n\t}),\n};\n\nMetadataCascadePoliciesListCommand.args = {\n\tfolderID: Args.string({\n\t\tname: 'folderID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The ID of the folder to list cascade policies for',\n\t}),\n};\n\nmodule.exports = MetadataCascadePoliciesListCommand;\n"
  },
  {
    "path": "src/commands/metadata-query.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst { omit, mapKeys, snakeCase } = require('lodash');\n\nconst parseQueryValue = (value) => {\n\tif (value.endsWith('f') && !Number.isNaN(Number.parseFloat(value))) {\n\t\treturn Number.parseFloat(value);\n\t}\n\treturn value;\n};\n\nclass MetadataQueryCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(MetadataQueryCommand);\n\n\t\tconst {\n\t\t\textra_fields: extraFields,\n\t\t\tquery_params: queryParameters,\n\t\t\tquery_param: queryParameter,\n\t\t\tquery_param_array: queryParameterArray,\n\t\t\t...rest\n\t\t} = mapKeys(omit(flags, Object.keys(BoxCommand.flags)), (value, key) =>\n\t\t\tsnakeCase(key)\n\t\t);\n\n\t\tlet combinedQueryParameters = queryParameters || {};\n\t\tif (queryParameter) {\n\t\t\tcombinedQueryParameters = {\n\t\t\t\t...combinedQueryParameters,\n\t\t\t\t...Object.assign({}, ...queryParameter),\n\t\t\t};\n\t\t}\n\t\tif (queryParameterArray) {\n\t\t\tcombinedQueryParameters = {\n\t\t\t\t...combinedQueryParameters,\n\t\t\t\t...Object.assign({}, ...queryParameterArray),\n\t\t\t};\n\t\t}\n\n\t\tconst items = await this.client.metadata.query(\n\t\t\targs.from,\n\t\t\targs.ancestorFolderId,\n\t\t\t{\n\t\t\t\t...(extraFields && { fields: extraFields }),\n\t\t\t\t...(combinedQueryParameters && {\n\t\t\t\t\tquery_params: combinedQueryParameters,\n\t\t\t\t}),\n\t\t\t\t...rest,\n\t\t\t}\n\t\t);\n\t\tawait this.output(items);\n\t}\n}\n\nMetadataQueryCommand.description =\n\t'Create a search using SQL-like syntax to return items that match specific metadata';\nMetadataQueryCommand.examples = [\n\t'box metadata-query enterprise_12345.someTemplate 5555 --query \"amount >= :minAmount AND amount <= :maxAmount\" --query-params minAmount=100f,maxAmount=200f --use-index amountAsc --order-by amount=ASC --extra-fields created_at,metadata.enterprise_1234.contracts',\n\t'box metadata-query enterprise_12345.contractTemplate 12345 --query \"status = :status\" --query-param status=active',\n];\nMetadataQueryCommand._endpoint = 'post_metadata_queries_execute_read';\n\nMetadataQueryCommand.flags = {\n\t...BoxCommand.flags,\n\tquery: Flags.string({\n\t\tdescription: 'The logical expression of the query',\n\t}),\n\t'query-params': Flags.string({\n\t\tdescription:\n\t\t\t'The arguments for the query. Can be specified as a comma-separated list of key-value pairs. i.e. key1=value1,key2=value2',\n\t\tdependsOn: ['query'],\n\t\tparse(input) {\n\t\t\treturn Object.assign(\n\t\t\t\t{},\n\t\t\t\t...input.split(',').map((parameter) => {\n\t\t\t\t\tconst [key, value] = parameter.split('=');\n\n\t\t\t\t\treturn {\n\t\t\t\t\t\t[key]: parseQueryValue(value),\n\t\t\t\t\t};\n\t\t\t\t})\n\t\t\t);\n\t\t},\n\t}),\n\t'query-param': Flags.string({\n\t\tdescription:\n\t\t\t'One query param key-value pair, i.e. key=value. If this key duplicates with query-params, this flag will take precedence.',\n\t\tdependsOn: ['query'],\n\t\tmultiple: true,\n\t\tparse(input) {\n\t\t\tconst key = input.split('=')[0];\n\t\t\tconst value = input.slice(Math.max(0, key.length + 1));\n\t\t\treturn {\n\t\t\t\t[key]: parseQueryValue(value),\n\t\t\t};\n\t\t},\n\t}),\n\t'query-param-array': Flags.string({\n\t\tdescription:\n\t\t\t'One query param key-multiple-value pair, use for multiple-values fields, i.e. key=value1,value2,value3. If this key duplicates with query-params or query-param, this flag will take precedence.',\n\t\tdependsOn: ['query'],\n\t\tmultiple: true,\n\t\tparse(input) {\n\t\t\tconst key = input.split('=')[0];\n\t\t\tconst value = input.slice(Math.max(0, key.length + 1)).split(',');\n\t\t\treturn {\n\t\t\t\t[key]: value.map((x) => parseQueryValue(x)),\n\t\t\t};\n\t\t},\n\t}),\n\t'use-index': Flags.string({\n\t\tdescription: 'The name of the search index to use for this query.',\n\t}),\n\t'order-by': Flags.string({\n\t\tdescription:\n\t\t\t'A list of template fields and directions to sort the metadata query results by.',\n\t\tparse(input) {\n\t\t\treturn input.split(',').map((parameter) => {\n\t\t\t\tconst [fieldKey, direction] = parameter.split('=');\n\t\t\t\treturn { field_key: fieldKey, direction };\n\t\t\t});\n\t\t},\n\t}),\n\tlimit: Flags.integer({\n\t\tdescription:\n\t\t\t'A value between 0 and 100 that indicates the maximum number of results to return for a single request. This only specifies a maximum boundary and will not guarantee the minimum number of results returned.',\n\t}),\n\tmarker: Flags.string({\n\t\tdescription: 'Marker to use for requesting the next page.',\n\t}),\n\t'extra-fields': Flags.string({\n\t\tdescription:\n\t\t\t'A list of additional attributes to return for any item, including its metadata.',\n\t\tparse(input) {\n\t\t\treturn input.split(',');\n\t\t},\n\t}),\n};\n\nMetadataQueryCommand.args = {\n\tfrom: Args.string({\n\t\tname: 'from',\n\t\trequired: true,\n\t\tdescription:\n\t\t\t'The template used in the query. Must be in the form scope.templateKey (for example enterprise_12345.contractTemplate)',\n\t}),\n\tancestorFolderId: Args.string({\n\t\tname: 'ancestorFolderId',\n\t\trequired: true,\n\t\tdescription: 'The folder_id to which to restrain the query',\n\t}),\n};\n\nmodule.exports = MetadataQueryCommand;\n"
  },
  {
    "path": "src/commands/metadata-templates/cascade.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass MetadataCascadePoliciesCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tMetadataCascadePoliciesCreateCommand\n\t\t);\n\n\t\tlet policy = await this.client.metadata.createCascadePolicy(\n\t\t\tflags.scope,\n\t\t\targs.templateKey,\n\t\t\tflags.folder\n\t\t);\n\t\tawait this.output(policy);\n\t}\n}\n\nMetadataCascadePoliciesCreateCommand.description =\n\t'Create a new metadata cascade policy on a folder';\nMetadataCascadePoliciesCreateCommand.examples = [\n\t'box metadata-templates:cascade employeeRecord --folder 22222',\n];\nMetadataCascadePoliciesCreateCommand._endpoint =\n\t'post_metadata_cascade_policies';\nMetadataCascadePoliciesCreateCommand.aliases = [\n\t'metadata-cascade-policies:create',\n];\n\nMetadataCascadePoliciesCreateCommand.flags = {\n\t...BoxCommand.flags,\n\t'id-only': Flags.boolean({\n\t\tdescription: 'Return only an ID to output from this command',\n\t}),\n\tscope: Flags.string({\n\t\tdescription: 'The scope of the metadata template to cascade',\n\t\tdefault: 'enterprise',\n\t}),\n\tfolder: Flags.string({\n\t\trequired: true,\n\t\tdescription: 'The ID of the folder to cascade metadata on',\n\t}),\n};\n\nMetadataCascadePoliciesCreateCommand.args = {\n\ttemplateKey: Args.string({\n\t\tname: 'templateKey',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The template key of the metadata template to cascade',\n\t}),\n};\n\nmodule.exports = MetadataCascadePoliciesCreateCommand;\n"
  },
  {
    "path": "src/commands/metadata-templates/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\nconst BoxCLIError = require('../../cli-error');\n\nconst FLAG_HANDLERS = Object.freeze({\n\tstring(value, currentField, template) {\n\t\ttemplate.fields.push(currentField);\n\n\t\treturn {\n\t\t\ttype: 'string',\n\t\t\tdisplayName: value.input,\n\t\t};\n\t},\n\tdate(value, currentField, template) {\n\t\ttemplate.fields.push(currentField);\n\n\t\treturn {\n\t\t\ttype: 'date',\n\t\t\tdisplayName: value.input,\n\t\t};\n\t},\n\tnumber(value, currentField, template) {\n\t\ttemplate.fields.push(currentField);\n\n\t\treturn {\n\t\t\ttype: 'float',\n\t\t\tdisplayName: value.input,\n\t\t};\n\t},\n\tenum(value, currentField, template) {\n\t\ttemplate.fields.push(currentField);\n\n\t\treturn {\n\t\t\ttype: 'enum',\n\t\t\tdisplayName: value.input,\n\t\t\toptions: [],\n\t\t};\n\t},\n\t'multi-select': (value, currentField, template) => {\n\t\ttemplate.fields.push(currentField);\n\n\t\treturn {\n\t\t\ttype: 'multiSelect',\n\t\t\tdisplayName: value.input,\n\t\t\toptions: [],\n\t\t};\n\t},\n\thidden(value, currentField, template) {\n\t\tlet isHidden = !value.input.startsWith('--no-');\n\n\t\tif (!currentField) {\n\t\t\ttemplate.hidden = isHidden;\n\t\t\treturn null;\n\t\t}\n\n\t\tcurrentField.hidden = isHidden;\n\t\treturn currentField;\n\t},\n\t'field-key': (value, currentField /* , template*/) => {\n\t\tif (!currentField) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Unexpected --field-key flag outside of field definition'\n\t\t\t);\n\t\t}\n\n\t\tcurrentField.key = value.input;\n\t\treturn currentField;\n\t},\n\tdescription(value, currentField /* , template*/) {\n\t\tif (!currentField) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Unexpected --description flag outside of field definition'\n\t\t\t);\n\t\t}\n\n\t\tcurrentField.description = value.input;\n\t\treturn currentField;\n\t},\n\toption(value, currentField /* , template*/) {\n\t\tif (!currentField) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Unexpected --option flag outside of field definition'\n\t\t\t);\n\t\t}\n\n\t\tif (\n\t\t\tcurrentField.type !== 'enum' &&\n\t\t\tcurrentField.type !== 'multiSelect'\n\t\t) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'--option flag can only be specified for enum and multi-select fields'\n\t\t\t);\n\t\t}\n\n\t\tcurrentField.options.push({ key: value.input });\n\t\treturn currentField;\n\t},\n});\n\n/**\n * Parses out field-related flags into the correct array of objects to pass\n * to the API.\n *\n * @param {Object[]} preparsedArgv The \"raw\" parsed args/flags from oclif\n * @returns {Object[]} The field definition array\n * @private\n */\nfunction _parseFlags(preparsedArgv) {\n\tlet template = {\n\t\tfields: [],\n\t};\n\n\tlet currentField = null;\n\n\tfor (const value of preparsedArgv.filter((v) => v.type === 'flag')) {\n\t\tlet handler =\n\t\t\tFLAG_HANDLERS[value.flag] ||\n\t\t\t((value_, currentField_) => currentField_);\n\t\tcurrentField = handler(value, currentField, template);\n\t}\n\n\t// Add the last field if necessary and return\n\ttemplate.fields = [...template.fields, currentField].filter(\n\t\t(op) => op !== null\n\t);\n\treturn template;\n}\n\nclass MetadataTemplatesCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, raw } = await this.parse(MetadataTemplatesCreateCommand);\n\n\t\tlet options = _parseFlags(raw);\n\n\t\tlet fields = options.fields;\n\t\tdelete options.fields;\n\n\t\toptions.scope = flags.scope;\n\n\t\tif (flags['template-key']) {\n\t\t\toptions.templateKey = flags['template-key'];\n\t\t}\n\n\t\tif (flags['copy-instance-on-item-copy']) {\n\t\t\toptions.copyInstanceOnItemCopy =\n\t\t\t\tflags['copy-instance-on-item-copy'];\n\t\t}\n\n\t\tlet template = await this.client.metadata.createTemplate(\n\t\t\tflags['display-name'],\n\t\t\tfields,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(template);\n\t}\n}\n\nMetadataTemplatesCreateCommand.description = 'Create a new metadata template';\nMetadataTemplatesCreateCommand.examples = [\n\t'box metadata-templates:create --display-name \"Employee Record\" --string Name --enum Department --option Sales',\n];\nMetadataTemplatesCreateCommand._endpoint = 'post_metadata_templates_schema';\n\nMetadataTemplatesCreateCommand.flags = {\n\t...BoxCommand.flags,\n\t'display-name': Flags.string({\n\t\tdescription: 'The display name of the metadata template',\n\t\trequired: true,\n\t}),\n\tscope: Flags.string({\n\t\tdescription: 'The scope of the metadata template',\n\t\tdefault: 'enterprise',\n\t}),\n\t'template-key': Flags.string({\n\t\tdescription:\n\t\t\t'A unique identifier for the template.  If not specified, will be derived from the display name',\n\t}),\n\thidden: Flags.boolean({\n\t\tdescription: 'Whether this template or field is hidden in the UI',\n\t\tallowNo: true,\n\t}),\n\tstring: Flags.string({\n\t\tdescription: 'Add a string field with the provided name',\n\t\tmultiple: true,\n\t}),\n\tenum: Flags.string({\n\t\tdescription: 'Add an enum field with the provided display name',\n\t\tmultiple: true,\n\t}),\n\tdate: Flags.string({\n\t\tdescription: 'Add a date field with the provided display name',\n\t\tmultiple: true,\n\t}),\n\tnumber: Flags.string({\n\t\tdescription: 'Add a numeric field with the provided display name',\n\t\tmultiple: true,\n\t}),\n\t'multi-select': Flags.string({\n\t\tdescription: 'Add a multi-select field with the provided display name',\n\t\tmultiple: true,\n\t}),\n\t'field-key': Flags.string({\n\t\tdescription: 'Set the key of a field',\n\t\tmultiple: true,\n\t}),\n\tdescription: Flags.string({\n\t\tdescription: 'Set the description of a field',\n\t\tmultiple: true,\n\t}),\n\toption: Flags.string({\n\t\tdescription: 'Add an option to a field',\n\t\tmultiple: true,\n\t}),\n\t'id-only': Flags.boolean({\n\t\tdescription: 'Return only an ID to output from this command',\n\t}),\n\t'copy-instance-on-item-copy': Flags.boolean({\n\t\tdescription:\n\t\t\t'Whether to include the metadata when a file or folder is copied',\n\t}),\n};\n\nmodule.exports = MetadataTemplatesCreateCommand;\n"
  },
  {
    "path": "src/commands/metadata-templates/delete.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass MetadataTemplatesDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tMetadataTemplatesDeleteCommand\n\t\t);\n\n\t\tawait this.client.metadata.deleteTemplate(\n\t\t\tflags.scope,\n\t\t\targs.templateKey\n\t\t);\n\t\tthis.info(\n\t\t\t`Delete metadata template with scope ${flags.scope} and identifier ${args.templateKey}`\n\t\t);\n\t}\n}\n\nMetadataTemplatesDeleteCommand.description = 'Delete a metadata template';\nMetadataTemplatesDeleteCommand.examples = [\n\t'box metadata-templates:delete employeeRecord',\n];\nMetadataTemplatesDeleteCommand._endpoint =\n\t'delete_metadata_templates_id_id_schema';\n\nMetadataTemplatesDeleteCommand.flags = {\n\t...BoxCommand.flags,\n\tscope: Flags.string({\n\t\tdescription: 'The scope of the metadata template to delete',\n\t\tdefault: 'enterprise',\n\t}),\n};\n\nMetadataTemplatesDeleteCommand.args = {\n\ttemplateKey: Args.string({\n\t\tname: 'templateKey',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The template key of the metadata template to delete',\n\t}),\n};\n\nmodule.exports = MetadataTemplatesDeleteCommand;\n"
  },
  {
    "path": "src/commands/metadata-templates/get.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass MetadataTemplatesGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(MetadataTemplatesGetCommand);\n\n\t\t// @TODO: Support get metadata template by ID\n\t\tlet template = await this.client.metadata.getTemplateSchema(\n\t\t\tflags.scope,\n\t\t\targs.templateKey\n\t\t);\n\t\tawait this.output(template);\n\t}\n}\n\nMetadataTemplatesGetCommand.description =\n\t'Get information about a metadata template';\nMetadataTemplatesGetCommand.examples = [\n\t'box metadata-templates:get employeeRecord',\n];\nMetadataTemplatesGetCommand._endpoint = 'get_metadata_templates_id_id_schema';\n\nMetadataTemplatesGetCommand.flags = {\n\t...BoxCommand.flags,\n\tscope: Flags.string({\n\t\tdescription: 'The scope of the metadata template to get',\n\t\tdefault: 'enterprise',\n\t}),\n};\n\nMetadataTemplatesGetCommand.args = {\n\ttemplateKey: Args.string({\n\t\tname: 'templateKey',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The template key of the template to get',\n\t}),\n};\n\nmodule.exports = MetadataTemplatesGetCommand;\n"
  },
  {
    "path": "src/commands/metadata-templates/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\n\nclass MetadataTemplatesListCommand extends BoxCommand {\n\tasync run() {\n\t\tawait this.parse(MetadataTemplatesListCommand);\n\n\t\tlet templates = await this.client.metadata.getTemplates('enterprise');\n\t\tawait this.output(templates);\n\t}\n}\n\nMetadataTemplatesListCommand.aliases = ['metadata-templates:list'];\n\nMetadataTemplatesListCommand.description =\n\t'Get all metadata templates in your Enterprise';\nMetadataTemplatesListCommand.examples = [\n\t'box metadata-templates:list',\n\t'box metadata-templates:list --json',\n\t'box metadata-templates:list --fields templateKey,displayName,scope',\n];\nMetadataTemplatesListCommand._endpoint = 'get_metadata_templates_enterprise';\n\nMetadataTemplatesListCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nmodule.exports = MetadataTemplatesListCommand;\n"
  },
  {
    "path": "src/commands/metadata-templates/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst BoxCLIError = require('../../cli-error');\n\nconst UNESCAPED_COMMA_REGEX = /(?<![^\\\\](?:\\\\\\\\)*\\\\),/gu;\nconst UNESCAPED_DOT_REGEX = /(?<![^\\\\](?:\\\\\\\\)*\\\\)\\./gu;\n\nconst FLAG_HANDLERS = Object.freeze({\n\t'add-enum-option': (value, currentOp, ops) => {\n\t\tops.push(currentOp);\n\n\t\treturn {\n\t\t\top: 'addEnumOption',\n\t\t\tfieldKey: value.input,\n\t\t\tdata: {},\n\t\t};\n\t},\n\t'reorder-enum-options': (value, currentOp, ops) => {\n\t\tops.push(currentOp);\n\n\t\treturn {\n\t\t\top: 'reorderEnumOptions',\n\t\t\tfieldKey: value.input,\n\t\t\tenumOptionKeys: [],\n\t\t};\n\t},\n\t'reorder-fields': (value, currentOp, ops) => {\n\t\tops.push(currentOp);\n\n\t\treturn {\n\t\t\top: 'reorderFields',\n\t\t\tfieldKeys: value.input\n\t\t\t\t.split(UNESCAPED_COMMA_REGEX)\n\t\t\t\t.filter((v) => v.length > 0),\n\t\t};\n\t},\n\t'edit-field': (value, currentOp, ops) => {\n\t\tops.push(currentOp);\n\n\t\treturn {\n\t\t\top: 'editField',\n\t\t\tfieldKey: value.input,\n\t\t\tdata: {},\n\t\t};\n\t},\n\t'edit-enum-option': (value, currentOp, ops) => {\n\t\tops.push(currentOp);\n\n\t\tlet keyParts = value.input\n\t\t\t.split(UNESCAPED_DOT_REGEX)\n\t\t\t.filter((v) => v.length > 0);\n\t\tif (!keyParts || keyParts.length !== 2) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Enum option key must be formatted as fieldKey.optionKey'\n\t\t\t);\n\t\t}\n\n\t\treturn {\n\t\t\top: 'editEnumOption',\n\t\t\tfieldKey: keyParts[0],\n\t\t\tenumOptionKey: keyParts[1],\n\t\t\tdata: {},\n\t\t};\n\t},\n\t'remove-enum-option': (value, currentOp, ops) => {\n\t\tops.push(currentOp);\n\n\t\tlet keyParts = value.input\n\t\t\t.split(UNESCAPED_DOT_REGEX)\n\t\t\t.filter((v) => v.length > 0);\n\t\tif (!keyParts || keyParts.length !== 2) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Enum option key must be formatted as fieldKey.optionKey'\n\t\t\t);\n\t\t}\n\n\t\treturn {\n\t\t\top: 'removeEnumOption',\n\t\t\tfieldKey: keyParts[0],\n\t\t\tenumOptionKey: keyParts[1],\n\t\t};\n\t},\n\t'remove-field': (value, currentOp, ops) => {\n\t\tops.push(currentOp);\n\n\t\treturn {\n\t\t\top: 'removeField',\n\t\t\tfieldKey: value.input,\n\t\t};\n\t},\n\toption(value, currentOp, ops) {\n\t\tif (!currentOp) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Unexpected --option flag outside of option-related operation'\n\t\t\t);\n\t\t}\n\n\t\tlet fieldType;\n\t\tswitch (currentOp.op) {\n\t\t\tcase 'addEnumOption': {\n\t\t\t\tif (currentOp.data.key) {\n\t\t\t\t\tops.push({ ...currentOp });\n\t\t\t\t\tcurrentOp.data = {};\n\t\t\t\t}\n\n\t\t\t\tcurrentOp.data.key = value.input;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'editEnumOption':\n\t\t\tcase 'addMultiSelectOption': {\n\t\t\t\tcurrentOp.data.key = value.input;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'reorderEnumOptions': {\n\t\t\t\tcurrentOp.enumOptionKeys.push(value.input);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'addField': {\n\t\t\t\tfieldType = currentOp.data.type;\n\t\t\t\tif (fieldType !== 'enum' && fieldType !== 'multiSelect') {\n\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t`Unexpected --option flag while specifying ${fieldType} field`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tcurrentOp.data.options.push({ key: value.input });\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t'Unexpected --option flag outside of option-related operation'\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn currentOp;\n\t},\n\t'field-key': (value, currentOp /* , ops*/) => {\n\t\tif (!currentOp) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Unexpected --field-key flag outside of field operation'\n\t\t\t);\n\t\t}\n\n\t\tswitch (currentOp.op) {\n\t\t\tcase 'editField':\n\t\t\tcase 'addField': {\n\t\t\t\tcurrentOp.data.key = value.input;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t'Unexpected --field-key flag outside of field add or edit operation'\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn currentOp;\n\t},\n\tdescription(value, currentOp /* , ops*/) {\n\t\tif (\n\t\t\t!currentOp ||\n\t\t\t(currentOp.op !== 'editField' && currentOp.op !== 'addField')\n\t\t) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Unexpected --description flag outside of field operation'\n\t\t\t);\n\t\t}\n\n\t\tcurrentOp.data.description = value.input;\n\t\treturn currentOp;\n\t},\n\thidden(value, currentOp /* , ops*/) {\n\t\tif (!currentOp) {\n\t\t\tcurrentOp = {\n\t\t\t\top: 'editTemplate',\n\t\t\t\tdata: {},\n\t\t\t};\n\t\t}\n\n\t\tswitch (currentOp.op) {\n\t\t\tcase 'editTemplate':\n\t\t\tcase 'editField':\n\t\t\tcase 'addField': {\n\t\t\t\tcurrentOp.data.hidden = !value.input.startsWith('--no-');\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t'Unexpected --hidden flag outside of template or field edit operation'\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn currentOp;\n\t},\n\t'copy-instance-on-item-copy': (value, currentOp /* , ops*/) => {\n\t\tif (!currentOp) {\n\t\t\tcurrentOp = {\n\t\t\t\top: 'editTemplate',\n\t\t\t\tdata: {},\n\t\t\t};\n\t\t}\n\n\t\tif (currentOp.op !== 'editTemplate') {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Unexpected --copy-instance-on-item-copy flag outside of template edit operation'\n\t\t\t);\n\t\t}\n\t\tcurrentOp.data.copyInstanceOnItemCopy =\n\t\t\t!value.input.startsWith('--no-');\n\t\treturn currentOp;\n\t},\n\t'display-name': (value, currentOp /* , ops*/) => {\n\t\tif (!currentOp) {\n\t\t\tcurrentOp = {\n\t\t\t\top: 'editTemplate',\n\t\t\t\tdata: {},\n\t\t\t};\n\t\t}\n\n\t\tswitch (currentOp.op) {\n\t\t\tcase 'editTemplate':\n\t\t\tcase 'editField': {\n\t\t\t\tcurrentOp.data.displayName = value.input;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t'Unexpected --display-name flag outside of template or field edit operation'\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\treturn currentOp;\n\t},\n\tstring(value, currentOp, ops) {\n\t\tops.push(currentOp);\n\n\t\treturn {\n\t\t\top: 'addField',\n\t\t\tdata: {\n\t\t\t\ttype: 'string',\n\t\t\t\tdisplayName: value.input,\n\t\t\t},\n\t\t};\n\t},\n\tenum(value, currentOp, ops) {\n\t\tops.push(currentOp);\n\n\t\treturn {\n\t\t\top: 'addField',\n\t\t\tdata: {\n\t\t\t\ttype: 'enum',\n\t\t\t\tdisplayName: value.input,\n\t\t\t\toptions: [],\n\t\t\t},\n\t\t};\n\t},\n\tnumber(value, currentOp, ops) {\n\t\tops.push(currentOp);\n\n\t\treturn {\n\t\t\top: 'addField',\n\t\t\tdata: {\n\t\t\t\ttype: 'float',\n\t\t\t\tdisplayName: value.input,\n\t\t\t},\n\t\t};\n\t},\n\tdate(value, currentOp, ops) {\n\t\tops.push(currentOp);\n\n\t\treturn {\n\t\t\top: 'addField',\n\t\t\tdata: {\n\t\t\t\ttype: 'date',\n\t\t\t\tdisplayName: value.input,\n\t\t\t},\n\t\t};\n\t},\n\t'multi-select': (value, currentOp, ops) => {\n\t\tops.push(currentOp);\n\n\t\treturn {\n\t\t\top: 'addField',\n\t\t\tdata: {\n\t\t\t\ttype: 'multiSelect',\n\t\t\t\tdisplayName: value.input,\n\t\t\t\toptions: [],\n\t\t\t},\n\t\t};\n\t},\n\t'add-multi-select-option': (value, currentOp, ops) => {\n\t\tops.push(currentOp);\n\n\t\treturn {\n\t\t\top: 'addMultiSelectOption',\n\t\t\tfieldKey: value.input,\n\t\t\tdata: {},\n\t\t};\n\t},\n});\n\n/**\n * Parses out field-related flags into the correct array of objects to pass\n * to the API.\n *\n * @param {Object[]} preparsedArgv The \"raw\" parsed args/flags from oclif\n * @returns {Object[]} The field definition array\n * @private\n */\nfunction _parseOperations(preparsedArgv) {\n\tlet ops = [],\n\t\tcurrentOp = null;\n\n\tfor (const value of preparsedArgv.filter((v) => v.type === 'flag')) {\n\t\tlet handler =\n\t\t\tFLAG_HANDLERS[value.flag] || ((value_, currentOp_) => currentOp_);\n\t\tcurrentOp = handler(value, currentOp, ops);\n\t}\n\n\t// Add the last field if necessary and return\n\treturn [...ops, currentOp].filter((op) => op !== null);\n}\n\nclass MetadataTemplatesUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args, raw } = await this.parse(\n\t\t\tMetadataTemplatesUpdateCommand\n\t\t);\n\t\tlet operations = _parseOperations(raw);\n\n\t\tlet template = await this.client.metadata.updateTemplate(\n\t\t\tflags.scope,\n\t\t\targs.templateKey,\n\t\t\toperations\n\t\t);\n\t\tawait this.output(template);\n\t}\n}\n\nMetadataTemplatesUpdateCommand.description = 'Update a metadata template';\nMetadataTemplatesUpdateCommand.examples = [\n\t'box metadata-templates:update employeeRecord --hidden',\n];\nMetadataTemplatesUpdateCommand._endpoints =\n\t'put_metadata_templates_id_id_schema';\n\nMetadataTemplatesUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\t'display-name': Flags.string({\n\t\tdescription: 'The display name of the metadata template or field',\n\t\tmultiple: true,\n\t}),\n\tscope: Flags.string({\n\t\tdescription: 'The scope of the metadata template',\n\t\tdefault: 'enterprise',\n\t}),\n\thidden: Flags.boolean({\n\t\tdescription: 'Whether this template or field is hidden in the UI',\n\t\tallowNo: true,\n\t}),\n\tstring: Flags.string({\n\t\tdescription: 'Add a string field with the provided name',\n\t\tmultiple: true,\n\t}),\n\tenum: Flags.string({\n\t\tdescription: 'Add an enum field with the provided display name',\n\t\tmultiple: true,\n\t}),\n\tdate: Flags.string({\n\t\tdescription: 'Add a date field with the provided display name',\n\t\tmultiple: true,\n\t}),\n\tnumber: Flags.string({\n\t\tdescription: 'Add a numeric field with the provided display name',\n\t\tmultiple: true,\n\t}),\n\t'multi-select': Flags.string({\n\t\tdescription: 'Add a multi-select field with the provided display name',\n\t\tmultiple: true,\n\t}),\n\t'add-multi-select-option': Flags.string({\n\t\tdescription:\n\t\t\t'Add an option to a specified multiselect field; must be followed by one or more --option flags',\n\t\tmultiple: true,\n\t}),\n\t'field-key': Flags.string({\n\t\tdescription: 'Set the key of a field',\n\t\tmultiple: true,\n\t}),\n\tdescription: Flags.string({\n\t\tdescription: 'Set the description of a field',\n\t\tmultiple: true,\n\t}),\n\toption: Flags.string({\n\t\tdescription: 'Specify a field option',\n\t\tmultiple: true,\n\t}),\n\t'add-enum-option': Flags.string({\n\t\tdescription:\n\t\t\t'Add an enum option to the specified field; must be followed by one or more --option flags',\n\t\tmultiple: true,\n\t}),\n\t'reorder-enum-options': Flags.string({\n\t\tdescription:\n\t\t\t'Reorder the options for a given field; must be followed by one or more --option flags',\n\t\tmultiple: true,\n\t}),\n\t'reorder-fields': Flags.string({\n\t\tdescription:\n\t\t\t'Reorder the template fields; must be in the form first_key,second_key,...',\n\t}),\n\t'edit-field': Flags.string({\n\t\tdescription:\n\t\t\t'Edit the specified field; must be followed by flags to apply to the field',\n\t}),\n\t'edit-enum-option': Flags.string({\n\t\tdescription:\n\t\t\t'Edit the specified enum option; must be followed by an --option flag',\n\t}),\n\t'remove-enum-option': Flags.string({\n\t\tdescription:\n\t\t\t'Removes the specified enum field option; must be in the form fieldKey.optionKey',\n\t}),\n\t'remove-field': Flags.string({\n\t\tdescription: 'Remove the specified field',\n\t}),\n\t'copy-instance-on-item-copy': Flags.boolean({\n\t\tdescription:\n\t\t\t'Whether to include the metadata when a file or folder is copied',\n\t\tallowNo: true,\n\t}),\n};\n\nMetadataTemplatesUpdateCommand.args = {\n\ttemplateKey: Args.string({\n\t\tname: 'templateKey',\n\t\tdescription: 'The key of the template to update',\n\t\thidden: false,\n\t\trequired: true,\n\t}),\n};\n\nmodule.exports = MetadataTemplatesUpdateCommand;\n"
  },
  {
    "path": "src/commands/oss.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../box-command');\nconst path = require('node:path');\nconst utilities = require('../util');\n\nclass OSSLicensesCommand extends BoxCommand {\n\tasync run() {\n\t\tlet licensesFilePath = path.resolve(\n\t\t\t__dirname,\n\t\t\t'../../LICENSE-THIRD-PARTY.txt'\n\t\t);\n\n\t\tlet licenseText = await utilities.readFileAsync(\n\t\t\tlicensesFilePath,\n\t\t\t'utf8'\n\t\t);\n\n\t\tawait this.output(licenseText);\n\t}\n}\n\nOSSLicensesCommand.noClient = true;\nOSSLicensesCommand.description =\n\t'Print a list of open-source licensed packages used in the Box CLI';\n\nOSSLicensesCommand.flags = {\n\t...BoxCommand.minFlags,\n};\n\nmodule.exports = OSSLicensesCommand;\n"
  },
  {
    "path": "src/commands/recent-items.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../box-command');\nconst PaginationUtilities = require('../pagination-utils');\n\nclass RecentItems extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(RecentItems);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet recentItems = await this.client.recentItems.get(options);\n\t\tawait this.output(recentItems);\n\t}\n}\n\nRecentItems.description =\n\t'List information about files accessed in the past 90 days up to a 1000 items';\nRecentItems.examples = ['box recent-items'];\nRecentItems._endpoint = 'get_recent_items';\n\nRecentItems.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nmodule.exports = RecentItems;\n"
  },
  {
    "path": "src/commands/request.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst querystring = require('node:querystring');\n\nclass ManualRequestCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(ManualRequestCommand);\n\n\t\tlet url = args.resource;\n\t\tlet parameters = {};\n\n\t\ttry {\n\t\t\tparameters.qs = JSON.parse(flags.query);\n\t\t} catch {\n\t\t\tparameters.qs = querystring.parse(flags.query);\n\t\t}\n\n\t\tif (Object.hasOwn(flags, 'body') && flags.body !== '') {\n\t\t\ttry {\n\t\t\t\tparameters.body = JSON.parse(flags.body);\n\t\t\t\tparameters.json = true;\n\t\t\t} catch {\n\t\t\t\tparameters.body = flags.body;\n\t\t\t\tparameters.headers = {\n\t\t\t\t\t'Content-Type': 'application/octet-stream',\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\t// Split the array of headers into an object like {header: value, header2: value2}\n\t\tif (flags.header) {\n\t\t\tparameters.headers = Object.fromEntries(\n\t\t\t\tflags.header\n\t\t\t\t\t.map((h) => h.split(/:\\s*/u))\n\t\t\t\t\t.map((kv) => [kv[0], kv[1]])\n\t\t\t);\n\t\t}\n\n\t\tlet response;\n\n\t\tswitch (flags.method) {\n\t\t\tcase 'GET': {\n\t\t\t\tresponse = await this.client.get(url, parameters);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'POST': {\n\t\t\t\tresponse = await this.client.post(url, parameters);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'PUT': {\n\t\t\t\tresponse = await this.client.put(url, parameters);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'DELETE': {\n\t\t\t\tresponse = await this.client.del(url, parameters);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'OPTIONS': {\n\t\t\t\tresponse = await this.client.options(url, parameters);\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tdefault: {\n\t\t\t\tthis.error(`Invalid method: ${flags.method}`);\n\t\t\t}\n\t\t}\n\n\t\tawait this.output({\n\t\t\tstatusCode: response.statusCode,\n\t\t\theaders: response.headers,\n\t\t\tbody: response.body,\n\t\t});\n\t}\n}\n\nManualRequestCommand.description = 'Manually specify a Box API request';\nManualRequestCommand.examples = [\n\t'box request /users/me',\n\t'box request /folders/0/items --query \"limit=5\"',\n\t'box request /folders -X POST --body \\'{\"name\":\"New Folder\",\"parent\":{\"id\":\"0\"}}\\'',\n];\n\nManualRequestCommand.flags = {\n\t...BoxCommand.flags,\n\tmethod: Flags.string({\n\t\tdescription: 'The HTTP method for the request',\n\t\toptions: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS'],\n\t\tdefault: 'GET',\n\t\tchar: 'X',\n\t}),\n\tquery: Flags.string({\n\t\tdescription:\n\t\t\t'Query params to use for the request, either as k1=v1&k2=v2 or as JSON',\n\t\tdefault: '',\n\t}),\n\tbody: Flags.string({\n\t\tdescription: 'Body of the request',\n\t\tdefault: '',\n\t}),\n\theader: Flags.string({\n\t\tdescription: 'HTTP header to add to the request, e.g. \"Header: value\"',\n\t\tmultiple: true,\n\t\tchar: 'H',\n\t}),\n};\n\nManualRequestCommand.args = {\n\tresource: Args.string({\n\t\tname: 'resource',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription:\n\t\t\t'The Box API resource to make a request against, e.g. /search or https://api.box.com/2.0/search',\n\t}),\n};\n\nmodule.exports = ManualRequestCommand;\n"
  },
  {
    "path": "src/commands/retention-policies/assign.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst BoxCLIError = require('../../cli-error');\nconst { Flags, Args } = require('@oclif/core');\n\nclass RetentionPoliciesAssignCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tRetentionPoliciesAssignCommand\n\t\t);\n\t\tlet assignment;\n\n\t\tlet assignType = flags['assign-to-type'];\n\t\tlet assignID = flags['assign-to-id'];\n\t\tlet options = {};\n\n\t\tif (Object.hasOwn(flags, 'filter-field')) {\n\t\t\toptions.filter_fields = flags['filter-field'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'start-date-field')) {\n\t\t\toptions.start_date_field = flags['start-date-field'];\n\t\t}\n\n\t\tif (assignType === 'enterprise') {\n\t\t\tassignment = await this.client.retentionPolicies.assign(\n\t\t\t\targs.policyID,\n\t\t\t\tassignType,\n\t\t\t\tnull,\n\t\t\t\toptions\n\t\t\t);\n\t\t} else {\n\t\t\tif (!assignID) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t'An ID of the content to assign the retention policy to is required'\n\t\t\t\t);\n\t\t\t}\n\t\t\tassignment = await this.client.retentionPolicies.assign(\n\t\t\t\targs.policyID,\n\t\t\t\tassignType,\n\t\t\t\tassignID,\n\t\t\t\toptions\n\t\t\t);\n\t\t}\n\t\tawait this.output(assignment);\n\t}\n}\n\nRetentionPoliciesAssignCommand.description =\n\t'Assign a retention policy assignment';\nRetentionPoliciesAssignCommand.examples = [\n\t'box retention-policies:assign 12345 --assign-to-type folder --assign-to-id 22222 --filter-field=fieldName=fieldValue --start-date-field=upload_date',\n];\nRetentionPoliciesAssignCommand._endpoint = 'post_retention_policy_assignments';\n\nRetentionPoliciesAssignCommand.flags = {\n\t...BoxCommand.flags,\n\t'assign-to-type': Flags.string({\n\t\tdescription:\n\t\t\t'The type of the content to assign the retention policy to',\n\t\trequired: true,\n\t\toptions: ['enterprise', 'folder', 'metadata_template'],\n\t}),\n\t'assign-to-id': Flags.string({\n\t\tdescription: 'The ID of the content to assign the retention policy to',\n\t}),\n\t'filter-field': Flags.string({\n\t\tdescription:\n\t\t\t'Metadata fields to filter against, if assigning to a metadata template.' +\n\t\t\t'Allow properties: field, value. Example: --filter-field=fieldName=fieldValue',\n\t\tmultiple: true,\n\t\tparse(input) {\n\t\t\tconst filter = {};\n\t\t\tinput = input.split('=');\n\t\t\tif (input.length !== 2) {\n\t\t\t\tthrow new BoxCLIError('Invalid filter field');\n\t\t\t}\n\t\t\tfilter.field = input[0];\n\t\t\tfilter.value = input[1];\n\t\t\treturn filter;\n\t\t},\n\t}),\n\t'start-date-field': Flags.string({\n\t\tdescription: 'The date the retention policy assignment begins',\n\t}),\n};\n\nRetentionPoliciesAssignCommand.args = {\n\tpolicyID: Args.string({\n\t\tname: 'policyID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The ID of the retention policy to assign this content to',\n\t}),\n};\n\nmodule.exports = RetentionPoliciesAssignCommand;\n"
  },
  {
    "path": "src/commands/retention-policies/assignments/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass RetentionPoliciesGetAssignmentCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tRetentionPoliciesGetAssignmentCommand\n\t\t);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet assignment = await this.client.retentionPolicies.getAssignment(\n\t\t\targs.id,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(assignment);\n\t}\n}\n\nRetentionPoliciesGetAssignmentCommand.description =\n\t'Get information about a retention policy assignment';\nRetentionPoliciesGetAssignmentCommand.examples = [\n\t'box retention-policies:assignments:get 1235',\n];\nRetentionPoliciesGetAssignmentCommand._endpoint =\n\t'get_retention_policy_assignments_id';\n\nRetentionPoliciesGetAssignmentCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nRetentionPoliciesGetAssignmentCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the retention policy assignment to get',\n\t}),\n};\n\nmodule.exports = RetentionPoliciesGetAssignmentCommand;\n"
  },
  {
    "path": "src/commands/retention-policies/assignments/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst PaginationUtilities = require('../../../pagination-utils');\n\nclass RetentionPoliciesListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(RetentionPoliciesListCommand);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.type) {\n\t\t\toptions.type = flags.type;\n\t\t}\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet assignments = await this.client.retentionPolicies.getAssignments(\n\t\t\targs.id,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(assignments);\n\t}\n}\n\nRetentionPoliciesListCommand.description =\n\t'List all retention policies for your enterprise';\nRetentionPoliciesListCommand.examples = [\n\t'box retention-policies:assignments 12345',\n];\nRetentionPoliciesListCommand._endpoint =\n\t'get_retention_policies_id_assignments';\n\nRetentionPoliciesListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n\ttype: Flags.string({\n\t\tdescription: 'The type of the retention policy assignment to retrieve',\n\t\toptions: ['folder', 'enterprise', 'metadata_template'],\n\t}),\n};\n\nRetentionPoliciesListCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the retention policy to get assignments for',\n\t}),\n};\n\nmodule.exports = RetentionPoliciesListCommand;\n"
  },
  {
    "path": "src/commands/retention-policies/assignments/remove.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass RetentionPoliciesRemoveAssignmentCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(\n\t\t\tRetentionPoliciesRemoveAssignmentCommand\n\t\t);\n\n\t\tawait this.client.retentionPolicies.deleteAssignment(args.id);\n\t\tthis.info(`Removed retention policy assignment ${args.id}`);\n\t}\n}\n\nRetentionPoliciesRemoveAssignmentCommand.description =\n\t'Remove a retention policy assignment applied to content';\nRetentionPoliciesRemoveAssignmentCommand.examples = [\n\t'box retention-policies:assignments:remove 1235',\n];\nRetentionPoliciesRemoveAssignmentCommand._endpoint =\n\t'delete_retention_policy_assignments_id';\n\nRetentionPoliciesRemoveAssignmentCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nRetentionPoliciesRemoveAssignmentCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the retention policy assignment to remove',\n\t}),\n};\n\nmodule.exports = RetentionPoliciesRemoveAssignmentCommand;\n"
  },
  {
    "path": "src/commands/retention-policies/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass RetentionPoliciesCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tRetentionPoliciesCreateCommand\n\t\t);\n\n\t\tlet policyType = 'indefinite';\n\t\tlet dispositionAction = flags['disposition-action'];\n\t\tlet options = {};\n\n\t\tif (Object.hasOwn(flags, 'notify-owners')) {\n\t\t\toptions.are_owners_notified = flags['notify-owners'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'allow-extension')) {\n\t\t\toptions.can_owner_extend_retention = flags['allow-extension'];\n\t\t}\n\t\tif (flags['retention-length']) {\n\t\t\tpolicyType = 'finite';\n\t\t\toptions.retention_length = flags['retention-length'];\n\t\t}\n\t\tif (flags['retention-type']) {\n\t\t\toptions.retention_type = flags['retention-type'];\n\t\t} else if (flags.modifiable) {\n\t\t\toptions.retention_type =\n\t\t\t\tthis.client.retentionPolicies.retentionTypes.MODIFIABLE;\n\t\t} else if (flags['non-modifiable']) {\n\t\t\toptions.retention_type =\n\t\t\t\tthis.client.retentionPolicies.retentionTypes.NON_MODIFIABLE;\n\t\t}\n\t\tif (Object.hasOwn(flags, 'description')) {\n\t\t\toptions.description = flags.description;\n\t\t}\n\t\tif (Object.hasOwn(flags, 'custom-notification-recipient')) {\n\t\t\toptions.custom_notification_recipients =\n\t\t\t\tflags['custom-notification-recipient'];\n\t\t}\n\n\t\tlet policy = await this.client.retentionPolicies.create(\n\t\t\targs.policyName,\n\t\t\tpolicyType,\n\t\t\tdispositionAction,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(policy);\n\t}\n}\n\nRetentionPoliciesCreateCommand.description = 'Create a new retention policy';\nRetentionPoliciesCreateCommand.examples = [\n\t'box retention-policies:create \"Tax Documents\" --retention-length 2555 --disposition-action=remove_retention --notify-owners --allow-extension --description \"Tax documents for 2018\" --custom-notification-recipient=id=12345,login=user@box.com',\n];\nRetentionPoliciesCreateCommand._endpoint = 'post_retention_policies';\n\nRetentionPoliciesCreateCommand.flags = {\n\t...BoxCommand.flags,\n\t'notify-owners': Flags.boolean({\n\t\tdescription:\n\t\t\t'The owner or co-owner will get notified when a file is nearing expiration',\n\t\tallowNo: true,\n\t}),\n\t'allow-extension': Flags.boolean({\n\t\tdescription:\n\t\t\t'The owner of a file will be allowed to extend the retention',\n\t\tallowNo: true,\n\t}),\n\t'retention-length': Flags.integer({\n\t\tchar: 'l',\n\t\tdescription:\n\t\t\t'The number of days to apply the retention policy. If not set, policy will be indefinite',\n\t}),\n\t'retention-type': Flags.string({\n\t\tdescription: 'The type of retention for the new policy',\n\t\texclusive: ['modifiable', 'non-modifiable'],\n\t\toptions: ['modifiable', 'non_modifiable'],\n\t}),\n\tmodifiable: Flags.boolean({\n\t\tdescription: 'Set retention type to modifiable',\n\t\thidden: true,\n\t\texclusive: ['retention-type', 'non-modifiable'],\n\t}),\n\t'non-modifiable': Flags.boolean({\n\t\tdescription: 'Set retention type to non_modifiable',\n\t\thidden: true,\n\t\texclusive: ['retention-type', 'modifiable'],\n\t}),\n\t'disposition-action': Flags.string({\n\t\trequired: true,\n\t\tdescription:\n\t\t\t'For indefinite policies, disposition action must be remove_retention',\n\t\toptions: ['permanently_delete', 'remove_retention'],\n\t}),\n\tdescription: Flags.string({\n\t\trequired: false,\n\t\tdescription: 'The additional text description of the retention policy',\n\t\tparse: utilities.unescapeSlashes,\n\t}),\n\t'custom-notification-recipient': Flags.string({\n\t\tdescription:\n\t\t\t'A list of users notified when the retention policy duration is about to end. ' +\n\t\t\t'Allowed properties are: id, type, login, name',\n\t\tmultiple: true,\n\t\tparse(input) {\n\t\t\tconst user = {\n\t\t\t\ttype: 'user',\n\t\t\t};\n\n\t\t\tfor (const part of input.split(',')) {\n\t\t\t\tconst [key, value] = part.split('=');\n\t\t\t\tuser[key] = value;\n\t\t\t}\n\t\t\treturn user;\n\t\t},\n\t}),\n};\n\nRetentionPoliciesCreateCommand.args = {\n\tpolicyName: Args.string({\n\t\tname: 'policyName',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Name of retention policy to be created',\n\t}),\n};\n\nmodule.exports = RetentionPoliciesCreateCommand;\n"
  },
  {
    "path": "src/commands/retention-policies/file-version-retentions/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass RetentionPoliciesGetVersionRetentionCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tRetentionPoliciesGetVersionRetentionCommand\n\t\t);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet retention =\n\t\t\tawait this.client.retentionPolicies.getFileVersionRetention(\n\t\t\t\targs.id,\n\t\t\t\toptions\n\t\t\t);\n\t\tawait this.output(retention);\n\t}\n}\n\nRetentionPoliciesGetVersionRetentionCommand.description =\n\t'Get information about a file version retention policy';\nRetentionPoliciesGetVersionRetentionCommand.examples = [\n\t'box retention-policies:file-version-retentions:get 77777',\n];\nRetentionPoliciesGetVersionRetentionCommand._endpoint =\n\t'get_file_version_retentions_id';\n\nRetentionPoliciesGetVersionRetentionCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nRetentionPoliciesGetVersionRetentionCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file version retention to get',\n\t}),\n};\n\nmodule.exports = RetentionPoliciesGetVersionRetentionCommand;\n"
  },
  {
    "path": "src/commands/retention-policies/file-version-retentions/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags } = require('@oclif/core');\nconst PaginationUtilities = require('../../../pagination-utils');\n\nclass RetentionPoliciesListVersionRetentionCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(\n\t\t\tRetentionPoliciesListVersionRetentionCommand\n\t\t);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags['disposition-action']) {\n\t\t\toptions.disposition_action = flags['disposition-action'];\n\t\t}\n\t\tif (flags['disposition-after']) {\n\t\t\toptions.disposition_after = flags['disposition-after'];\n\t\t}\n\t\tif (flags['disposition-before']) {\n\t\t\toptions.disposition_before = flags['disposition-before'];\n\t\t}\n\t\tif (flags['file-id']) {\n\t\t\toptions.file_id = flags['file-id'];\n\t\t}\n\t\tif (flags['file-version-id']) {\n\t\t\toptions.file_version_id = flags['file-version-id'];\n\t\t}\n\t\tif (flags['policy-id']) {\n\t\t\toptions.policy_id = flags['policy-id'];\n\t\t}\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet retentions =\n\t\t\tawait this.client.retentionPolicies.getAllFileVersionRetentions(\n\t\t\t\toptions\n\t\t\t);\n\t\tawait this.output(retentions);\n\t}\n}\n\nRetentionPoliciesListVersionRetentionCommand.description =\n\t'List all file version retentions for your enterprise';\nRetentionPoliciesListVersionRetentionCommand.examples = [\n\t'box retention-policies:file-version-retentions',\n];\nRetentionPoliciesListVersionRetentionCommand._endpoint =\n\t'get_file_version_retentions';\n\nRetentionPoliciesListVersionRetentionCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n\t'disposition-action': Flags.string({\n\t\tdescription: 'A disposition action to filter by',\n\t\toptions: ['permanently_delete', 'remove_retention'],\n\t}),\n\t'disposition-after': Flags.string({\n\t\tdescription:\n\t\t\t'A date to filter retention policies that complete after a certain time',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'disposition-before': Flags.string({\n\t\tdescription:\n\t\t\t'A date to filter retention policies that complete before a certain time',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'file-id': Flags.string({\n\t\tdescription: 'A file id to filter the file version retentions by',\n\t}),\n\t'file-version-id': Flags.string({\n\t\tdescription:\n\t\t\t'A file version id to filter the file version retentions by',\n\t}),\n\t'policy-id': Flags.string({\n\t\tdescription: 'A policy id to filter the file version retentions by',\n\t}),\n};\n\nmodule.exports = RetentionPoliciesListVersionRetentionCommand;\n"
  },
  {
    "path": "src/commands/retention-policies/file-versions-under-retention/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\nconst PaginationUtilities = require('../../../pagination-utils');\n\nclass RetentionPoliciesGetFileVersionsRetentionForAssignmentCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tRetentionPoliciesGetFileVersionsRetentionForAssignmentCommand\n\t\t);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet fileVersions =\n\t\t\tawait this.client.retentionPolicies.getFileVersionsUnderRetentionForAssignment(\n\t\t\t\targs.id,\n\t\t\t\toptions\n\t\t\t);\n\t\tawait this.output(fileVersions);\n\t}\n}\n\nRetentionPoliciesGetFileVersionsRetentionForAssignmentCommand.description =\n\t'Get information about file versions under retention for assignment';\nRetentionPoliciesGetFileVersionsRetentionForAssignmentCommand.examples = [\n\t'box retention-policies:file-versions-under-retention:get 77777',\n];\nRetentionPoliciesGetFileVersionsRetentionForAssignmentCommand._endpoint =\n\t'get_retention_policy_assignments_id_file_versions_under_retention';\nRetentionPoliciesGetFileVersionsRetentionForAssignmentCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nRetentionPoliciesGetFileVersionsRetentionForAssignmentCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the retention policy assignment',\n\t}),\n};\n\nmodule.exports = RetentionPoliciesGetFileVersionsRetentionForAssignmentCommand;\n"
  },
  {
    "path": "src/commands/retention-policies/files-under-retention/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\nconst PaginationUtilities = require('../../../pagination-utils');\n\nclass RetentionPoliciesGetFilesRetentionForAssignmentCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tRetentionPoliciesGetFilesRetentionForAssignmentCommand\n\t\t);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet files =\n\t\t\tawait this.client.retentionPolicies.getFilesUnderRetentionForAssignment(\n\t\t\t\targs.id,\n\t\t\t\toptions\n\t\t\t);\n\t\tawait this.output(files);\n\t}\n}\n\nRetentionPoliciesGetFilesRetentionForAssignmentCommand.description =\n\t'Get information about files under retention for assignment';\nRetentionPoliciesGetFilesRetentionForAssignmentCommand.examples = [\n\t'box retention-policies:files-under-retention:get 77777',\n];\nRetentionPoliciesGetFilesRetentionForAssignmentCommand._endpoint =\n\t'get_retention_policy_assignments_id_files_under_retention';\n\nRetentionPoliciesGetFilesRetentionForAssignmentCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nRetentionPoliciesGetFilesRetentionForAssignmentCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the retention policy assignment',\n\t}),\n};\n\nmodule.exports = RetentionPoliciesGetFilesRetentionForAssignmentCommand;\n"
  },
  {
    "path": "src/commands/retention-policies/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass RetentionPoliciesGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(RetentionPoliciesGetCommand);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet policy = await this.client.retentionPolicies.get(args.id, options);\n\t\tawait this.output(policy);\n\t}\n}\n\nRetentionPoliciesGetCommand.description =\n\t'Get information about a retention policy';\nRetentionPoliciesGetCommand.examples = ['box retention-policies:get 12345'];\nRetentionPoliciesGetCommand._endpoint = 'get_retention_policies_id';\n\nRetentionPoliciesGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nRetentionPoliciesGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the retention policy to get',\n\t}),\n};\n\nmodule.exports = RetentionPoliciesGetCommand;\n"
  },
  {
    "path": "src/commands/retention-policies/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass RetentionPoliciesListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(RetentionPoliciesListCommand);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags['policy-name']) {\n\t\t\toptions.policy_name = flags['policy-name'];\n\t\t}\n\t\tif (flags['policy-type']) {\n\t\t\toptions.policy_type = flags['policy-type'];\n\t\t}\n\t\tif (flags['created-by-user-id']) {\n\t\t\toptions.created_by_user_id = flags['created-by-user-id'];\n\t\t}\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet policies = await this.client.retentionPolicies.getAll(options);\n\t\tawait this.output(policies);\n\t}\n}\n\nRetentionPoliciesListCommand.description =\n\t'List all retention policies for your enterprise';\nRetentionPoliciesListCommand.examples = ['box retention-policies'];\nRetentionPoliciesListCommand._endpoint = 'get_retention_policies';\n\nRetentionPoliciesListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n\t'policy-name': Flags.string({\n\t\tchar: 'n',\n\t\tdescription: 'A name to filter the retention policies by',\n\t}),\n\t'policy-type': Flags.string({\n\t\tdescription: 'A policy type to filter the retention policies by',\n\t\toptions: ['finite', 'indefinite'],\n\t}),\n\t'created-by-user-id': Flags.string({\n\t\tchar: 'u',\n\t\tdescription: 'A user id to filter the retention policies by',\n\t}),\n};\n\nmodule.exports = RetentionPoliciesListCommand;\n"
  },
  {
    "path": "src/commands/retention-policies/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass RetentionPoliciesUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tRetentionPoliciesUpdateCommand\n\t\t);\n\t\tlet updates = {};\n\n\t\tif (flags['disposition-action']) {\n\t\t\tupdates.disposition_action = flags['disposition-action'];\n\t\t}\n\t\tif (flags['policy-name']) {\n\t\t\tupdates.policy_name = flags['policy-name'];\n\t\t}\n\t\tif (flags['policy-type']) {\n\t\t\tupdates.policy_type = flags['policy-type'];\n\t\t}\n\t\tif (flags['retention-length']) {\n\t\t\tupdates.retention_length = Number.parseInt(\n\t\t\t\tflags['retention-length'],\n\t\t\t\t10\n\t\t\t);\n\t\t}\n\t\tif (flags['non-modifiable']) {\n\t\t\tupdates.retention_type =\n\t\t\t\tthis.client.retentionPolicies.retentionTypes.NON_MODIFIABLE;\n\t\t}\n\t\tif (flags.retire) {\n\t\t\tupdates.status = 'retired';\n\t\t}\n\n\t\tif (Object.hasOwn(flags, 'notify-owners')) {\n\t\t\tupdates.are_owners_notified = flags['notify-owners'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'allow-extension')) {\n\t\t\tupdates.can_owner_extend_retention = flags['allow-extension'];\n\t\t}\n\n\t\tlet policy = await this.client.retentionPolicies.update(\n\t\t\targs.id,\n\t\t\tupdates\n\t\t);\n\t\tawait this.output(policy);\n\t}\n}\n\nRetentionPoliciesUpdateCommand.description = 'Update a retention policy';\nRetentionPoliciesUpdateCommand.examples = [\n\t'box retention-policies:update 12345',\n];\nRetentionPoliciesUpdateCommand._endpoint = 'put_retention_policies_id';\n\nRetentionPoliciesUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\t'disposition-action': Flags.string({\n\t\tchar: 'a',\n\t\tdescription:\n\t\t\t'For indefinite policies, disposition action must be remove_retention',\n\t}),\n\t'policy-name': Flags.string({\n\t\tchar: 'n',\n\t\tdescription: 'New name of retention policy',\n\t}),\n\t'policy-type': Flags.string({\n\t\tdescription: 'Type of policy',\n\t\toptions: ['finite', 'indefinite'],\n\t}),\n\t'retention-length': Flags.string({\n\t\tchar: 'l',\n\t\tdescription:\n\t\t\t'The amount of time, in days, to apply the retention policy. Required for finite policies',\n\t}),\n\t'non-modifiable': Flags.boolean({\n\t\tdescription: 'Set retention type to non_modifiable. ',\n\t}),\n\tretire: Flags.boolean({\n\t\tchar: 'r',\n\t\tdescription: 'Retire a retention policy',\n\t}),\n\t'notify-owners': Flags.boolean({\n\t\tdescription:\n\t\t\t'The owner or co-owner will get notified when a file is nearing expiration',\n\t\tallowNo: true,\n\t}),\n\t'allow-extension': Flags.boolean({\n\t\tdescription:\n\t\t\t'The owner of a file will be allowed to extend the retention',\n\t\tallowNo: true,\n\t}),\n};\n\nRetentionPoliciesUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the retention policy to update',\n\t}),\n};\n\nmodule.exports = RetentionPoliciesUpdateCommand;\n"
  },
  {
    "path": "src/commands/search.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst _ = require('lodash');\nconst os = require('node:os');\nconst BoxCLIError = require('../cli-error');\nconst PaginationUtilities = require('../pagination-utils');\n\nconst RESULTS_LIMIT = 100;\n\n/**\n * Parses a metadata value from the command line into the correct type\n * @param {string} value The value from command line flag\n * @returns {string|number} The parsed value\n * @private\n */\nfunction parseMetadataValue(value) {\n\tif (value.endsWith('f')) {\n\t\t// Attempt to parse as a numeric type\n\t\treturn Number.parseFloat(value) || value;\n\t}\n\n\treturn value;\n}\n\nclass SearchCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(SearchCommand);\n\t\tconst hasVerboseMetadataFilters =\n\t\t\tflags['md-filter-scope'] &&\n\t\t\tflags['md-filter-template-key'] &&\n\t\t\tflags['md-filter-json'];\n\t\tconst hasMetadataFilters = hasVerboseMetadataFilters || flags.mdfilter;\n\t\tconst query = args.query?.trim();\n\n\t\t// Require at least a search query or metadata filters, unless running in bulk mode\n\t\t// where parameters come from the bulk input file rather than command-line arguments.\n\t\tif (!query && !hasMetadataFilters && !this.isBulk) {\n\t\t\tconst missingQueryMessage = [\n\t\t\t\t'Missing required argument: [QUERY]',\n\t\t\t\t'Usage: box search \"your search terms\"',\n\t\t\t\t'Example: box search \"quarterly report\" --type file',\n\t\t\t\t'Run: box search --help for all available filters.',\n\t\t\t].join(os.EOL);\n\n\t\t\tthrow new BoxCLIError(missingQueryMessage);\n\t\t}\n\n\t\tif (flags.all && (flags.limit || flags['max-items'])) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'--all and --limit(--max-items) flags cannot be used together.'\n\t\t\t);\n\t\t}\n\n\t\tif (\n\t\t\tflags.limit &&\n\t\t\tflags['max-items'] &&\n\t\t\tflags.limit !== flags['max-items']\n\t\t) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t' --limit and --max-items flags cannot be used together.'\n\t\t\t);\n\t\t}\n\n\t\tif (!flags.all && !flags['max-items']) {\n\t\t\tflags['max-items'] = flags.limit || RESULTS_LIMIT;\n\t\t\tthis.flags['max-items'] = flags['max-items'];\n\t\t}\n\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.scope) {\n\t\t\toptions.scope = flags.scope;\n\t\t}\n\t\tif (flags.type) {\n\t\t\toptions.type = flags.type;\n\t\t}\n\t\tif (flags['file-extensions']) {\n\t\t\toptions.file_extensions = flags['file-extensions'];\n\t\t}\n\t\tif (hasVerboseMetadataFilters) {\n\t\t\tif (\n\t\t\t\tflags['md-filter-scope'].length ===\n\t\t\t\t\tflags['md-filter-template-key'].length &&\n\t\t\t\tflags['md-filter-scope'].length ===\n\t\t\t\t\tflags['md-filter-json'].length\n\t\t\t) {\n\t\t\t\toptions.mdfilters = [];\n\t\t\t\tfor (\n\t\t\t\t\tlet index = 0;\n\t\t\t\t\tindex < flags['md-filter-scope'].length;\n\t\t\t\t\tindex++\n\t\t\t\t) {\n\t\t\t\t\tlet filter = {\n\t\t\t\t\t\tscope: flags['md-filter-scope'][index],\n\t\t\t\t\t\ttemplateKey: flags['md-filter-template-key'][index],\n\t\t\t\t\t};\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfilter.filters = JSON.parse(\n\t\t\t\t\t\t\tflags['md-filter-json'][index]\n\t\t\t\t\t\t);\n\t\t\t\t\t} catch (error) {\n\t\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t\t'Could not parse metadata filter JSON',\n\t\t\t\t\t\t\terror\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\toptions.mdfilters.push(filter);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\"Mismatch on metadata filtering. Can't perform search.\"\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tif (flags.mdfilter) {\n\t\t\t// Transform the array of mdfilter objects into an object of arrays, grouped by template scope/key\n\t\t\t// e.g. { \"enterprise.myTemplate\": [filter1, filter2], \"global.properties\": [filter3]}\n\t\t\tlet groupedFilters = _.groupBy(\n\t\t\t\tflags.mdfilter,\n\t\t\t\t(filter) => `${filter.scope}.${filter.templateKey}`\n\t\t\t);\n\t\t\toptions.mdfilters = Object.keys(groupedFilters).map((key) => {\n\t\t\t\tlet [scope, templateKey] = key.split('.');\n\n\t\t\t\tlet filters = groupedFilters[key],\n\t\t\t\t\tfiltersObject = {};\n\n\t\t\t\t// Build the filters object, e.g {\"field1\": value1, \"field2\": {\"lt\": value2}}\n\t\t\t\tfor (const { field, cmp, value } of filters) {\n\t\t\t\t\tswitch (cmp) {\n\t\t\t\t\t\tcase '=': {\n\t\t\t\t\t\t\tfiltersObject[field] =\n\t\t\t\t\t\t\t\ttypeof value === 'number'\n\t\t\t\t\t\t\t\t\t? { lt: value, gt: value }\n\t\t\t\t\t\t\t\t\t: value;\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase '<': {\n\t\t\t\t\t\t\tfiltersObject[field] = { lt: value };\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tcase '>': {\n\t\t\t\t\t\t\tfiltersObject[field] = { gt: value };\n\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefault: {\n\t\t\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t\t\t'Invalid comparator specified in metadata filter'\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\tscope,\n\t\t\t\t\ttemplateKey,\n\t\t\t\t\tfilters: filtersObject,\n\t\t\t\t};\n\t\t\t});\n\t\t}\n\t\tif (flags['content-types']) {\n\t\t\toptions.content_types = flags['content-types'];\n\t\t}\n\t\tif (flags['ancestor-folder-ids']) {\n\t\t\toptions.ancestor_folder_ids = flags['ancestor-folder-ids'];\n\t\t}\n\t\tif (flags['owner-user-ids']) {\n\t\t\toptions.owner_user_ids = flags['owner-user-ids'];\n\t\t}\n\t\tif (flags['created-at-from']) {\n\t\t\toptions.created_at_range = `${flags['created-at-from']},`;\n\t\t}\n\t\tif (flags['created-at-to']) {\n\t\t\tif (options.created_at_range) {\n\t\t\t\toptions.created_at_range += flags['created-at-to'];\n\t\t\t} else {\n\t\t\t\toptions.created_at_range = `,${flags['created-at-to']}`;\n\t\t\t}\n\t\t}\n\t\tif (flags['updated-at-from']) {\n\t\t\toptions.updated_at_range = `${flags['updated-at-from']},`;\n\t\t}\n\t\tif (flags['updated-at-to']) {\n\t\t\tif (options.updated_at_range) {\n\t\t\t\toptions.updated_at_range += flags['updated-at-to'];\n\t\t\t} else {\n\t\t\t\toptions.updated_at_range = `,${flags['updated-at-to']}`;\n\t\t\t}\n\t\t}\n\t\tif (flags['trash-content']) {\n\t\t\toptions.trash_content = flags['trash-content'];\n\t\t}\n\t\tif (\n\t\t\tObject.hasOwn(flags, 'size-from') ||\n\t\t\tObject.hasOwn(flags, 'size-to')\n\t\t) {\n\t\t\toptions.size_range = `${_.get(flags, 'size-from', '')},${_.get(flags, 'size-to', '')}`;\n\t\t}\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tif (flags.sort) {\n\t\t\toptions.sort = flags.sort;\n\t\t}\n\n\t\tif (flags.direction) {\n\t\t\toptions.direction = flags.direction;\n\t\t}\n\n\t\tif (Object.hasOwn(flags, 'include-recent-shared-links')) {\n\t\t\toptions.include_recent_shared_links =\n\t\t\t\tflags['include-recent-shared-links'];\n\t\t}\n\n\t\tlet results = await this.client.search.query(query || null, options);\n\n\t\tawait this.output(results);\n\t}\n}\n\nSearchCommand.description = 'Search for files and folders in your Enterprise';\nSearchCommand.examples = [\n\t'box search \"Q3 OKR\"',\n\t'box search --mdfilter \"enterprise.employeeRecord.name=John Doe\"',\n];\nSearchCommand._endpoint = 'get_search';\n\nSearchCommand.flags = {\n\t...BoxCommand.flags,\n\tscope: Flags.string({\n\t\tdescription: 'The scope on which you want search',\n\t\toptions: ['user_content', 'enterprise_content'],\n\t}),\n\ttype: Flags.string({\n\t\tdescription:\n\t\t\t'The type of objects you want to include in the search results',\n\t\toptions: ['file', 'folder', 'web_link'],\n\t}),\n\t'file-extensions': Flags.string({\n\t\tdescription:\n\t\t\t'Limit searches to specific file extensions i.e. png,md,pdf',\n\t}),\n\t'md-filter-scope': Flags.string({\n\t\tdescription: 'Scope for metadata filter, can use multiple times',\n\t\tdependsOn: ['md-filter-template-key', 'md-filter-json'],\n\t\thidden: true,\n\t\tmultiple: true,\n\t}),\n\t'md-filter-template-key': Flags.string({\n\t\tdescription: 'Template key for metadata filter, can use multiple times',\n\t\tdependsOn: ['md-filter-scope', 'md-filter-json'],\n\t\thidden: true,\n\t\tmultiple: true,\n\t}),\n\t'md-filter-json': Flags.string({\n\t\tdescription:\n\t\t\t'JSON string of metadata to filter search, can use multiple times',\n\t\tdependsOn: ['md-filter-scope', 'md-filter-template-key'],\n\t\thidden: true,\n\t\tmultiple: true,\n\t}),\n\tmdfilter: Flags.string({\n\t\tdescription:\n\t\t\t'Metadata value to filter on, in the format <scope>.<templateKey>.<field>=<value>. For enterprise templates, scope is usually enterprise_<enterpriseID> (for example enterprise_123456).',\n\t\texclusive: [\n\t\t\t'md-filter-scope',\n\t\t\t'md-filter-template-key',\n\t\t\t'md-filter-json',\n\t\t],\n\t\tmultiple: true,\n\t\tparse(value_) {\n\t\t\tlet match = value_.match(/^(\\w+)\\.([\\w-]+)\\.([\\w-]+)([=<>])(.+)$/u);\n\t\t\tif (!match) {\n\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t`--mdfilter flag must be in scope.templateKey.field=value format; got ${value_} instead`\n\t\t\t\t);\n\t\t\t}\n\t\t\tlet [, scope, templateKey, field, cmp, value] = match;\n\t\t\treturn {\n\t\t\t\tscope,\n\t\t\t\ttemplateKey,\n\t\t\t\tfield,\n\t\t\t\tcmp,\n\t\t\t\tvalue: parseMetadataValue(value),\n\t\t\t};\n\t\t},\n\t}),\n\t'content-types': Flags.string({\n\t\tdescription:\n\t\t\t'Search for objects of specified content types. Requires a content type or a set of comma-delimited content types',\n\t}),\n\t'ancestor-folder-ids': Flags.string({\n\t\tdescription:\n\t\t\t'Search for the contents of specific folders (and folders within them). Requires a folder ID or a set of comma-delimited folder IDs',\n\t}),\n\t'owner-user-ids': Flags.string({\n\t\tdescription:\n\t\t\t'Search for objects by owner. Requires a user ID or a set of comma-delimited user IDs',\n\t}),\n\t'created-at-from': Flags.string({\n\t\tdescription:\n\t\t\t'Start of created date range. Use a RFC3339 timestamp or shorthand syntax 0t, like 5w for 5 weeks',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'created-at-to': Flags.string({\n\t\tdescription:\n\t\t\t'End of created date range. Use a RFC3339 timestamp or shorthand syntax 0t, like 5w for 5 weeks',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'updated-at-from': Flags.string({\n\t\tdescription:\n\t\t\t'Start of updated date range. Use a RFC3339 timestamp or shorthand syntax 0t, like 5w for 5 weeks',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'updated-at-to': Flags.string({\n\t\tdescription:\n\t\t\t'End of updated date range. Use a RFC3339 timestamp or shorthand syntax 0t, like 5w for 5 weeks',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'trash-content': Flags.string({\n\t\tdescription:\n\t\t\t'Controls whether to search in the trash. Defaults to non_trashed_only',\n\t\toptions: ['trashed_only', 'non_trashed_only'],\n\t}),\n\t'size-from': Flags.integer({\n\t\tdescription: 'Lower bound for file size, in bytes',\n\t}),\n\t'size-to': Flags.integer({\n\t\tdescription: 'Upper bound for file size, in bytes',\n\t}),\n\tsort: Flags.string({\n\t\tdescription: 'The field to sort results by',\n\t}),\n\tdirection: Flags.string({\n\t\tdescription: 'The direction to sort results (ascending or descending)',\n\t\tdependsOn: ['sort'],\n\t\toptions: ['asc', 'desc'],\n\t}),\n\tlimit: Flags.integer({\n\t\tdescription:\n\t\t\t'Defines the maximum number of items to return. Default value is 100.',\n\t}),\n\t'max-items': Flags.integer({\n\t\tdescription:\n\t\t\t'A value that indicates the maximum number of results to return.',\n\t\thidden: true,\n\t}),\n\tall: Flags.boolean({\n\t\tdescription: 'Returns all search results.',\n\t}),\n\t'include-recent-shared-links': Flags.boolean({\n\t\tdescription: 'Returns shared links that the user recently accessed',\n\t}),\n};\n\nSearchCommand.args = {\n\tquery: Args.string({\n\t\tname: 'query',\n\t\trequired: false,\n\t\thidden: false,\n\t\tdescription: `The search term. Some queries with special characters (e.g. double quotes for exact match) may require escaping (e.g. box search '\\\\\"query_term\\\\\"').`,\n\t\tdefault: '',\n\t}),\n};\n\nmodule.exports = SearchCommand;\n"
  },
  {
    "path": "src/commands/shared-links/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst SharedLinksModule = require('../../modules/shared-links');\n\nclass SharedLinksCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(SharedLinksCreateCommand);\n\n\t\tlet sharedLinksModule = new SharedLinksModule(this.client);\n\t\tlet updatedItem = await sharedLinksModule.createSharedLink(args, flags);\n\t\tawait this.output(updatedItem);\n\t}\n}\n\nSharedLinksCreateCommand.aliases = ['shared-links:update'];\n\nSharedLinksCreateCommand.description = 'Create a shared link for a Box item';\nSharedLinksCreateCommand.examples = [\n\t'box shared-links:create 22222 folder --access company --vanity-name my-custom-name-123',\n];\n\nconst sharedLinkFlags = {\n\t...BoxCommand.flags,\n\taccess: Flags.string({ description: 'Shared link access level' }),\n\tpassword: Flags.string({ description: 'Shared link password' }),\n\t'unshared-at': Flags.string({\n\t\tdescription:\n\t\t\t'Time that this link will become disabled. Use s for seconds, m for minutes, h for hours, d for days, w for weeks, M for months. For example, 30 seconds is 30s from now.',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'can-download': Flags.boolean({\n\t\tdescription: 'Whether the shared link allows downloads',\n\t\tallowNo: true,\n\t}),\n\t'vanity-name': Flags.string({\n\t\tdescription:\n\t\t\t'Defines a custom vanity name to use in the shared link URL. It should be between 12 and 30 characters. This field can contains only letters, numbers and hyphens.',\n\t}),\n};\n\nconst sharedLinkFileFlags = {\n\t'can-edit': Flags.boolean({\n\t\tdescription:\n\t\t\t'Whether the shared link allows edits. Only Applicable for files.',\n\t\tallowNo: true,\n\t}),\n};\n\nSharedLinksCreateCommand.flags = {\n\t...sharedLinkFlags,\n\t...sharedLinkFileFlags,\n};\n\nSharedLinksCreateCommand.args = {\n\titemID: Args.string({\n\t\tname: 'itemID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the Box item to share',\n\t}),\n\titemType: Args.string({\n\t\tname: 'itemType',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Type of item for shared link: either file or folder',\n\t\toptions: ['file', 'folder'],\n\t}),\n};\n\nmodule.exports = {\n\tSharedLinksCreateCommand,\n\tsharedLinkFlags,\n\tsharedLinkFileFlags,\n};\n"
  },
  {
    "path": "src/commands/shared-links/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\nconst chalk = require('chalk');\nconst SharedLinksModule = require('../../modules/shared-links');\n\nclass SharedLinksDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(SharedLinksDeleteCommand);\n\n\t\tlet sharedLinksModule = new SharedLinksModule(this.client);\n\t\tlet item = await sharedLinksModule.removeSharedLink(args);\n\t\tthis.info(\n\t\t\tchalk`{green Removed shared link from ${args.itemType} \"${item.name}\"}`\n\t\t);\n\t}\n}\n\nSharedLinksDeleteCommand.description = 'Delete a shared link for a Box item';\nSharedLinksDeleteCommand.examples = ['box shared-links:delete 22222 folder'];\n\nSharedLinksDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nSharedLinksDeleteCommand.args = {\n\titemID: Args.string({\n\t\tname: 'itemID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the Box item to remove the shared link from',\n\t}),\n\titemType: Args.string({\n\t\tname: 'itemType',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Type of item for shared link: either file or folder',\n\t\toptions: ['file', 'folder'],\n\t}),\n};\n\nmodule.exports = SharedLinksDeleteCommand;\n"
  },
  {
    "path": "src/commands/shared-links/get.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass SharedLinksGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(SharedLinksGetCommand);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet sharedItem = await this.client.sharedItems.get(\n\t\t\targs.url,\n\t\t\targs.password,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(sharedItem);\n\t}\n}\n\nSharedLinksGetCommand.description = 'Get information from a shared item URL';\nSharedLinksGetCommand.examples = [\n\t'box shared-links:get https://app.box.com/s/13ynxiqe3y4tup3j0yn4qairs5ebfxo3',\n];\nSharedLinksGetCommand._endpoint = 'get_shared_items';\n\nSharedLinksGetCommand.flags = {\n\t...BoxCommand.flags,\n\tpassword: Flags.string({\n\t\tdescription: 'Shared item password',\n\t\tdefault: null,\n\t}),\n};\n\nSharedLinksGetCommand.args = {\n\turl: Args.string({\n\t\tname: 'url',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Shared item URL to resolve',\n\t}),\n};\n\nmodule.exports = SharedLinksGetCommand;\n"
  },
  {
    "path": "src/commands/sign-requests/cancel.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass SignRequestsCancelCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(SignRequestsCancelCommand);\n\n\t\tconst signRequest = await this.client.signRequests.cancelById({\n\t\t\tsign_request_id: args.id,\n\t\t});\n\t\tawait this.output(signRequest);\n\t}\n}\n\nSignRequestsCancelCommand.description = 'Cancel sign request';\nSignRequestsCancelCommand.examples = ['box sign-requests:cancel 12345'];\nSignRequestsCancelCommand._endpoint = 'post_sign_requests_id_cancel';\n\nSignRequestsCancelCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nSignRequestsCancelCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The ID of the sign request',\n\t}),\n};\n\nmodule.exports = SignRequestsCancelCommand;\n"
  },
  {
    "path": "src/commands/sign-requests/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { omit, mapKeys, snakeCase } = require('lodash');\nconst { Flags } = require('@oclif/core');\nconst BoxCLIError = require('../../cli-error');\n\nconst ALLOWED_SIGNER_ROLES = ['signer', 'approver', 'final_copy_reader'];\n\nclass SignRequestsCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(SignRequestsCreateCommand);\n\n\t\tconst {\n\t\t\tsigner: signers,\n\t\t\tprefill_tag: prefillTags,\n\t\t\tdocument_preparation_needed: isDocumentPreparationNeeded,\n\t\t\ttext_signatures_enabled: areTextSignaturesEnabled,\n\t\t\treminders_enabled: areRemindersEnabled,\n\t\t\ttemplate_id: templateId,\n\t\t\t...rest\n\t\t} = mapKeys(omit(flags, Object.keys(BoxCommand.flags)), (value, key) =>\n\t\t\tsnakeCase(key)\n\t\t);\n\n\t\tconst signRequest = await this.client.signRequests.create({\n\t\t\tsigners,\n\t\t\tprefill_tags: prefillTags,\n\t\t\tis_document_preparation_needed: isDocumentPreparationNeeded,\n\t\t\tare_text_signatures_enabled: areTextSignaturesEnabled,\n\t\t\tare_reminders_enabled: areRemindersEnabled,\n\t\t\ttemplate_id: templateId,\n\t\t\t...rest,\n\t\t});\n\n\t\tawait this.output(signRequest);\n\t}\n}\n\nSignRequestsCreateCommand.description = 'Create sign request';\nSignRequestsCreateCommand.examples = [\n\t'box sign-requests:create --signer email=alice@example.com --source-files 12345 --parent-folder 23456  --prefill-tag id=1,value=Test',\n];\nSignRequestsCreateCommand._endpoint = 'post_sign_requests';\n\nSignRequestsCreateCommand.flags = {\n\t...BoxCommand.flags,\n\tsigner: Flags.string({\n\t\trequired: true,\n\t\tdescription:\n\t\t\t'A signer for the sign request. 35 is the max number of signers permitted. Can be added multiple times. ' +\n\t\t\t'Allowed (recommended) properties: email,role,is-in-person,order,embed-url-external-user-id,redirect-url,declined-redirect-url,group-id ' +\n\t\t\t'but snake case is also supported for: is_in_person,order,embed_url_external_user_id,redirect_url,declined_redirect_url,group_id',\n\t\tmultiple: true,\n\t\tparse(input) {\n\t\t\tconst signer = {\n\t\t\t\trole: 'signer',\n\t\t\t};\n\n\t\t\tfor (const part of input.split(',')) {\n\t\t\t\tconst [key, value] = part.split('=');\n\n\t\t\t\tswitch (key) {\n\t\t\t\t\tcase 'email': {\n\t\t\t\t\t\tsigner.email = value;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase 'role': {\n\t\t\t\t\t\tif (!ALLOWED_SIGNER_ROLES.includes(value)) {\n\t\t\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t\t\t`Invalid value for role property of signer: ${value}. Expecting one of: ${ALLOWED_SIGNER_ROLES.join(\n\t\t\t\t\t\t\t\t\t', '\n\t\t\t\t\t\t\t\t)}.`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsigner.role = value;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase 'is-in-person':\n\t\t\t\t\tcase 'is_in_person': {\n\t\t\t\t\t\tif (value !== '0' && value !== '1') {\n\t\t\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t\t\t`Invalid value for is_in_person property of signer: ${value}. Expecting either 0 or 1.`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tsigner.is_in_person = value === '1';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase 'order': {\n\t\t\t\t\t\tsigner.order = value;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase 'embed-url-external-user-id':\n\t\t\t\t\tcase 'embed_url_external_user_id': {\n\t\t\t\t\t\tsigner.embed_url_external_user_id = value;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase 'redirect_url':\n\t\t\t\t\tcase 'redirect-url': {\n\t\t\t\t\t\tsigner.redirect_url = value;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase 'declined-redirect-url':\n\t\t\t\t\tcase 'declined_redirect_url': {\n\t\t\t\t\t\tsigner.declined_redirect_url = value;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase 'signer-group-id':\n\t\t\t\t\tcase 'signer_group_id':\n\t\t\t\t\tcase 'group-id':\n\t\t\t\t\tcase 'group_id': {\n\t\t\t\t\t\tsigner.signer_group_id = value;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t\t`Unknown property for signer: ${key}`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn signer;\n\t\t},\n\t}),\n\t'source-files': Flags.string({\n\t\tdescription:\n\t\t\t'Comma separated list of files to create a signing document from. This is currently limited to 10 files, e.g. 12345',\n\t\tparse: (input) =>\n\t\t\tinput.split(',').map((id) => ({\n\t\t\t\ttype: 'file',\n\t\t\t\tid,\n\t\t\t})),\n\t}),\n\t'parent-folder': Flags.string({\n\t\tdescription:\n\t\t\t'The destination folder to place final, signed document and signing log',\n\t\tparse: (input) => ({\n\t\t\ttype: 'folder',\n\t\t\tid: input,\n\t\t}),\n\t}),\n\t'document-preparation-needed': Flags.boolean({\n\t\tdescription:\n\t\t\t'Indicates if the sender should receive a `prepare_url` in the response to complete document preparation via UI.',\n\t\tallowNo: true,\n\t}),\n\t'text-signatures-enabled': Flags.boolean({\n\t\tdescription:\n\t\t\t'Disables the usage of signatures generated by typing (text)',\n\t\tallowNo: true,\n\t}),\n\t'email-subject': Flags.string({\n\t\tdescription:\n\t\t\t'Subject of sign request email. This is cleaned by sign request. If this field is not passed, a default subject will be used.',\n\t}),\n\t'email-message': Flags.string({\n\t\tdescription:\n\t\t\t'Message to include in sign request email. The field is cleaned through sanitization of specific characters. However, some html tags are allowed. Links included in the message are also converted to hyperlinks in the email. The message may contain the following html tags including `a`, `abbr`, `acronym`, `b`, `blockquote`, `code`, `em`, `i`, `ul`, `li`, `ol`, and `strong`. Be aware that when the text to html ratio is too high, the email may end up in spam filters. Custom styles on these tags are not allowed. If this field is not passed, a default message will be used.',\n\t}),\n\t'reminders-enabled': Flags.boolean({\n\t\tdescription:\n\t\t\t'Reminds signers to sign a document on day 3, 8, 13 and 18. Reminders are only sent to outstanding signers.',\n\t\tallowNo: true,\n\t}),\n\t'prefill-tag': Flags.string({\n\t\tdescription:\n\t\t\t'Prefills a sign related tag in the content. Pass in a comma-separated dictionary of fields: id,text,checkbox,date. Can be added multiple times.',\n\t\tmultiple: true,\n\t\tparse(input) {\n\t\t\tconst prefillTag = {};\n\n\t\t\tfor (const part of input.split(',')) {\n\t\t\t\tconst [key, value] = part.split('=');\n\n\t\t\t\tswitch (key) {\n\t\t\t\t\tcase 'id': {\n\t\t\t\t\t\tprefillTag.document_tag_id = value;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase 'text': {\n\t\t\t\t\t\tprefillTag.text_value = value;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase 'checkbox': {\n\t\t\t\t\t\tif (value !== '0' && value !== '1') {\n\t\t\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t\t\t`Invalid value for checkbox property of prefill-tag: ${value}. Expecting either 0 or 1.`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\tprefillTag.checkbox_value = value === '1';\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tcase 'date': {\n\t\t\t\t\t\tprefillTag.date_value = value;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tdefault: {\n\t\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t\t`Unknown property for prefill-tag: ${key}`\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn prefillTag;\n\t\t},\n\t}),\n\t'days-valid': Flags.integer({\n\t\tdescription:\n\t\t\t'Number of days after which this request will automatically expire if not completed',\n\t}),\n\t'external-id': Flags.string({\n\t\tdescription:\n\t\t\t'This can be used to reference an ID in an external system that the sign request is related to.',\n\t}),\n\t'redirect-url': Flags.string({\n\t\tdescription:\n\t\t\t'The URL that a signer will be redirected to after signing a document. Defining this URL overrides the default redirect URL for all signers. If no declined redirect URL is specified, this URL will be used for decline actions as well.',\n\t}),\n\t'declined-redirect-url': Flags.string({\n\t\tdescription:\n\t\t\t'The URL that a signer will be redirected to after declining to sign a document. Defining this URL overrides the default redirect URL for all signers.',\n\t}),\n\t'template-id': Flags.string({\n\t\tdescription:\n\t\t\t'When a signature request is created from a template this field will indicate the id of that template.',\n\t}),\n};\n\nmodule.exports = SignRequestsCreateCommand;\n"
  },
  {
    "path": "src/commands/sign-requests/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass SignRequestsGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(SignRequestsGetCommand);\n\n\t\tconst signRequest = await this.client.signRequests.getById({\n\t\t\tsign_request_id: args.id,\n\t\t});\n\t\tawait this.output(signRequest);\n\t}\n}\n\nSignRequestsGetCommand.description = 'Get sign request by ID';\nSignRequestsGetCommand.examples = ['box sign-requests:get 12345'];\nSignRequestsGetCommand._endpoint = 'get_sign_requests_id';\n\nSignRequestsGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nSignRequestsGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The ID of the sign request',\n\t}),\n};\n\nmodule.exports = SignRequestsGetCommand;\n"
  },
  {
    "path": "src/commands/sign-requests/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\n\nclass SignRequestsListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(SignRequestsListCommand);\n\t\tconst { limit, marker } = flags;\n\n\t\tconst signRequests = await this.client.signRequests.getAll({\n\t\t\tlimit,\n\t\t\tmarker,\n\t\t});\n\n\t\tawait this.output(signRequests);\n\t}\n}\n\nSignRequestsListCommand.description = 'List sign requests';\nSignRequestsListCommand.examples = ['box sign-requests'];\nSignRequestsListCommand._endpoint = 'get_sign_requests';\n\nSignRequestsListCommand.flags = {\n\t...BoxCommand.flags,\n\tlimit: Flags.integer({\n\t\tdescription: 'The maximum number of items to return per page.',\n\t}),\n\tmarker: Flags.string({\n\t\tdescription:\n\t\t\t'Defines the position marker at which to begin returning results. This is used when paginating using marker-based pagination. This requires `usemarker` to be set to `true`.',\n\t}),\n};\n\nmodule.exports = SignRequestsListCommand;\n"
  },
  {
    "path": "src/commands/sign-requests/resend.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass SignRequestsResendCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(SignRequestsResendCommand);\n\n\t\tawait this.client.signRequests.resendById({\n\t\t\tsign_request_id: args.id,\n\t\t});\n\t\tthis.info(`Resent sign request ${args.id}`);\n\t}\n}\n\nSignRequestsResendCommand.description = 'Resend sign request';\nSignRequestsResendCommand.examples = ['box sign-requests:resend 12345'];\nSignRequestsResendCommand._endpoint = 'post_sign_requests_id_resend';\n\nSignRequestsResendCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nSignRequestsResendCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The ID of the sign request',\n\t}),\n};\n\nmodule.exports = SignRequestsResendCommand;\n"
  },
  {
    "path": "src/commands/sign-templates/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass SignTemplatesGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(SignTemplatesGetCommand);\n\n\t\tconst signTemplate = await this.client.signTemplates.getById({\n\t\t\ttemplate_id: args.id,\n\t\t});\n\t\tawait this.output(signTemplate);\n\t}\n}\n\nSignTemplatesGetCommand.description = 'Get sign template by ID';\nSignTemplatesGetCommand.examples = ['box sign-templates:get 12345'];\nSignTemplatesGetCommand._endpoint = 'get_sign_templates_id';\n\nSignTemplatesGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nSignTemplatesGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The ID of the sign template',\n\t}),\n};\n\nmodule.exports = SignTemplatesGetCommand;\n"
  },
  {
    "path": "src/commands/sign-templates/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\n\nclass SignTemplatesListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(SignTemplatesListCommand);\n\t\tconst { limit, marker } = flags;\n\n\t\tconst signTemplates = await this.client.signTemplates.getAll({\n\t\t\tlimit,\n\t\t\tmarker,\n\t\t});\n\n\t\tawait this.output(signTemplates);\n\t}\n}\n\nSignTemplatesListCommand.description = 'List sign templates';\nSignTemplatesListCommand.examples = ['box sign-templates'];\nSignTemplatesListCommand._endpoint = 'get_sign_templates';\n\nSignTemplatesListCommand.flags = {\n\t...BoxCommand.flags,\n\tlimit: Flags.integer({\n\t\tdescription: 'The maximum number of items to return per page.',\n\t}),\n\tmarker: Flags.string({\n\t\tdescription:\n\t\t\t'Defines the position marker at which to begin returning results. This is used when paginating using marker-based pagination. This requires `usemarker` to be set to `true`.',\n\t}),\n};\n\nmodule.exports = SignTemplatesListCommand;\n"
  },
  {
    "path": "src/commands/storage-policies/assign.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass StoragePoliciesAssignCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(StoragePoliciesAssignCommand);\n\n\t\tlet assignment = await this.client.storagePolicies.assign(\n\t\t\targs.storagePolicyID,\n\t\t\targs.userID\n\t\t);\n\t\tawait this.output(assignment);\n\t}\n}\n\nStoragePoliciesAssignCommand.description = 'Assign a storage policy';\nStoragePoliciesAssignCommand.examples = [\n\t'box storage-policies:assign 12345 33333',\n];\n\nStoragePoliciesAssignCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nStoragePoliciesAssignCommand.args = {\n\tstoragePolicyID: Args.string({\n\t\tname: 'storagePolicyID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Id of the storage policy',\n\t}),\n\tuserID: Args.string({\n\t\tname: 'userID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Id of the user to assign the storage policy to',\n\t}),\n};\n\nmodule.exports = StoragePoliciesAssignCommand;\n"
  },
  {
    "path": "src/commands/storage-policies/assignments/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass StoragePoliciesGetAssignmentCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(StoragePoliciesGetAssignmentCommand);\n\n\t\tlet assignment = await this.client.storagePolicies.getAssignment(\n\t\t\targs.id\n\t\t);\n\t\tawait this.output(assignment);\n\t}\n}\n\nStoragePoliciesGetAssignmentCommand.description =\n\t'Get information on a storage policy assignment';\nStoragePoliciesGetAssignmentCommand.examples = [\n\t'box storage-policies:assignments:get 12345',\n];\nStoragePoliciesGetAssignmentCommand._endpoint =\n\t'get_storage_policy_assignments_id';\n\nStoragePoliciesGetAssignmentCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nStoragePoliciesGetAssignmentCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the storage policy assignment to get',\n\t}),\n};\n\nmodule.exports = StoragePoliciesGetAssignmentCommand;\n"
  },
  {
    "path": "src/commands/storage-policies/assignments/lookup.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass StoragePoliciesListAssignmentsCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tStoragePoliciesListAssignmentsCommand\n\t\t);\n\n\t\tlet options = {\n\t\t\ttargetType: flags.type,\n\t\t};\n\n\t\tlet assignment =\n\t\t\tawait this.client.storagePolicies.getAssignmentForTarget(\n\t\t\t\targs.id,\n\t\t\t\toptions\n\t\t\t);\n\t\tawait this.output(assignment);\n\t}\n}\n\nStoragePoliciesListAssignmentsCommand.description =\n\t'Look up which storage policy an object is assigned to';\nStoragePoliciesListAssignmentsCommand.examples = [\n\t'box storage-policies:assignments:lookup 33333',\n];\nStoragePoliciesListAssignmentsCommand._endpoint =\n\t'get_storage_policy_assignments';\n\nStoragePoliciesListAssignmentsCommand.flags = {\n\t...BoxCommand.flags,\n\ttype: Flags.string({\n\t\trequired: true,\n\t\tdescription: 'Type of object to look up the storage policy for',\n\t\toptions: ['user', 'enterprise'],\n\t\tdefault: 'user',\n\t}),\n};\n\nStoragePoliciesListAssignmentsCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the object to look up the storage policy for',\n\t}),\n};\n\nmodule.exports = StoragePoliciesListAssignmentsCommand;\n"
  },
  {
    "path": "src/commands/storage-policies/assignments/remove.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass StoragePoliciesDeleteAssignmentCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(\n\t\t\tStoragePoliciesDeleteAssignmentCommand\n\t\t);\n\n\t\tawait this.client.storagePolicies.removeAssignment(args.id);\n\t\tthis.info(`Deleted storage policy assignment ${args.id}`);\n\t}\n}\n\nStoragePoliciesDeleteAssignmentCommand.description =\n\t'Delete a storage policy assignment';\nStoragePoliciesDeleteAssignmentCommand.examples = [\n\t'box storage-policies:assignments:remove 12345',\n];\nStoragePoliciesDeleteAssignmentCommand._endpoint =\n\t'delete_storage_policy_assignments_id';\n\nStoragePoliciesDeleteAssignmentCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nStoragePoliciesDeleteAssignmentCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the storage policy assignment to delete',\n\t}),\n};\n\nmodule.exports = StoragePoliciesDeleteAssignmentCommand;\n"
  },
  {
    "path": "src/commands/storage-policies/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass StoragePoliciesGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(StoragePoliciesGetCommand);\n\n\t\tlet storagePolicy = await this.client.storagePolicies.get(args.id);\n\t\tawait this.output(storagePolicy);\n\t}\n}\n\nStoragePoliciesGetCommand.description = 'Get information on a storage policy';\nStoragePoliciesGetCommand.examples = ['box storage-policies:get 12345'];\nStoragePoliciesGetCommand._endpoint = 'get_storage_policies_id';\n\nStoragePoliciesGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nStoragePoliciesGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the storage policy to get',\n\t}),\n};\n\nmodule.exports = StoragePoliciesGetCommand;\n"
  },
  {
    "path": "src/commands/storage-policies/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass StoragePoliciesListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(StoragePoliciesListCommand);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tlet storagePolicies = await this.client.storagePolicies.getAll(options);\n\t\tawait this.output(storagePolicies);\n\t}\n}\n\nStoragePoliciesListCommand.aliases = ['storage-policies:list'];\n\nStoragePoliciesListCommand.description = 'List storage policies';\nStoragePoliciesListCommand.examples = ['box storage-policies'];\nStoragePoliciesListCommand._endpoint = 'get_storage_policies';\n\nStoragePoliciesListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nmodule.exports = StoragePoliciesListCommand;\n"
  },
  {
    "path": "src/commands/tasks/assign.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass TaskAssignmentsCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(TaskAssignmentsCreateCommand);\n\t\tlet assignment;\n\n\t\tif (flags['assign-to-user-id']) {\n\t\t\tassignment = await this.client.tasks.assignByUserID(\n\t\t\t\targs.taskID,\n\t\t\t\tflags['assign-to-user-id']\n\t\t\t);\n\t\t} else if (flags['assign-to-user-login']) {\n\t\t\tassignment = await this.client.tasks.assignByEmail(\n\t\t\t\targs.taskID,\n\t\t\t\tflags['assign-to-user-login']\n\t\t\t);\n\t\t}\n\t\tawait this.output(assignment);\n\t}\n}\n\nTaskAssignmentsCreateCommand.aliases = ['task-assignments:create'];\n\nTaskAssignmentsCreateCommand.description = 'Create a task assignment';\nTaskAssignmentsCreateCommand.examples = [\n\t'box tasks:assign 88888 --assign-to-user-id 33333',\n];\nTaskAssignmentsCreateCommand._endpoint = 'post_task_assignments';\n\nTaskAssignmentsCreateCommand.flags = {\n\t...BoxCommand.flags,\n\t'assign-to-user-id': Flags.string({\n\t\tdescription: 'Assign task by user ID',\n\t\texclusive: ['assign-to-user-login'],\n\t}),\n\t'assign-to-user-login': Flags.string({\n\t\tdescription: 'Assign task by user login',\n\t\texclusive: ['assign-to-user-id'],\n\t}),\n};\n\nTaskAssignmentsCreateCommand.args = {\n\ttaskID: Args.string({\n\t\tname: 'taskID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the task to assign',\n\t}),\n};\n\nmodule.exports = TaskAssignmentsCreateCommand;\n"
  },
  {
    "path": "src/commands/tasks/assignments/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass TaskAssignmentsDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(TaskAssignmentsDeleteCommand);\n\n\t\tawait this.client.tasks.deleteAssignment(args.id);\n\t\tthis.info(`Successfully deleted task assignment ${args.id}`);\n\t}\n}\n\nTaskAssignmentsDeleteCommand.aliases = ['task-assignments:delete'];\n\nTaskAssignmentsDeleteCommand.description = 'Delete a task assignment';\nTaskAssignmentsDeleteCommand.examples = ['box tasks:assignments:delete 12345'];\nTaskAssignmentsDeleteCommand._endpoint = 'delete_task_assignments_id';\n\nTaskAssignmentsDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nTaskAssignmentsDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the task assignment to delete',\n\t}),\n};\n\nmodule.exports = TaskAssignmentsDeleteCommand;\n"
  },
  {
    "path": "src/commands/tasks/assignments/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass TaskAssignmentsGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(TaskAssignmentsGetCommand);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet assignment = await this.client.tasks.getAssignment(\n\t\t\targs.id,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(assignment);\n\t}\n}\n\nTaskAssignmentsGetCommand.aliases = ['task-assignments:get'];\n\nTaskAssignmentsGetCommand.description =\n\t'Get information about a task assignment';\nTaskAssignmentsGetCommand.examples = ['box tasks:assignments:get 12345'];\nTaskAssignmentsGetCommand._endpoint = 'get_task_assignments_id';\n\nTaskAssignmentsGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nTaskAssignmentsGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the task assignment to get',\n\t}),\n};\n\nmodule.exports = TaskAssignmentsGetCommand;\n"
  },
  {
    "path": "src/commands/tasks/assignments/index.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass TaskAssignmentsListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(TaskAssignmentsListCommand);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet assignments = await this.client.tasks.getAssignments(\n\t\t\targs.id,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(assignments);\n\t}\n}\n\nTaskAssignmentsListCommand.aliases = ['task-assignments:list'];\n\nTaskAssignmentsListCommand.description = 'List all task assignments on a task';\nTaskAssignmentsListCommand.examples = ['box tasks:assignments 88888'];\nTaskAssignmentsListCommand._endpoint = 'get_tasks_id_assignments';\n\nTaskAssignmentsListCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nTaskAssignmentsListCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the task to get assignments for',\n\t}),\n};\n\nmodule.exports = TaskAssignmentsListCommand;\n"
  },
  {
    "path": "src/commands/tasks/assignments/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass TaskAssignmentsUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(TaskAssignmentsUpdateCommand);\n\t\tlet options = {};\n\n\t\tif (flags.message) {\n\t\t\toptions.message = flags.message;\n\t\t}\n\t\tif (flags.completed) {\n\t\t\toptions.resolution_state =\n\t\t\t\tthis.client.tasks.resolutionStates.COMPLETE;\n\t\t} else if (flags.incomplete) {\n\t\t\toptions.resolution_state =\n\t\t\t\tthis.client.tasks.resolutionStates.INCOMPLETE;\n\t\t} else if (flags.approved) {\n\t\t\toptions.resolution_state =\n\t\t\t\tthis.client.tasks.resolutionStates.APPROVED;\n\t\t} else if (flags.rejected) {\n\t\t\toptions.resolution_state =\n\t\t\t\tthis.client.tasks.resolutionStates.REJECTED;\n\t\t}\n\t\tif (flags.status) {\n\t\t\toptions.resolution_state = flags.status;\n\t\t}\n\n\t\tlet assignment = await this.client.tasks.updateAssignment(\n\t\t\targs.id,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(assignment);\n\t}\n}\n\nTaskAssignmentsUpdateCommand.aliases = ['task-assignments:update'];\n\nTaskAssignmentsUpdateCommand.description = 'Update a task assignment';\nTaskAssignmentsUpdateCommand.examples = [\n\t'box tasks:assignments:update 12345 --status approved',\n];\nTaskAssignmentsUpdateCommand._endpoint = 'put_task_assignments_id';\n\nTaskAssignmentsUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\tmessage: Flags.string({\n\t\tdescription: 'A message from the assignee about this task',\n\t}),\n\tstatus: Flags.string({\n\t\tdescription: 'Set the resolution state of the task assignment',\n\t\texclusive: ['completed', 'incomplete', 'approved', 'rejected'],\n\t\toptions: ['completed', 'incomplete', 'approved', 'rejected'],\n\t}),\n\tcompleted: Flags.boolean({\n\t\tdescription: 'Change resolution state to completed',\n\t\thidden: true,\n\t\texclusive: ['incomplete', 'approved', 'rejected', 'status'],\n\t}),\n\tincomplete: Flags.boolean({\n\t\tdescription: 'Change resolution state to incomplete',\n\t\thidden: true,\n\t\texclusive: ['rejected', 'approved', 'completed', 'status'],\n\t}),\n\tapproved: Flags.boolean({\n\t\tdescription: 'Change resolution state to approved',\n\t\thidden: true,\n\t\texclusive: ['incomplete', 'completed', 'rejected', 'status'],\n\t}),\n\trejected: Flags.boolean({\n\t\tdescription: 'Change resolution state to rejected',\n\t\thidden: true,\n\t\texclusive: ['incomplete', 'approved', 'completed', 'status'],\n\t}),\n};\n\nTaskAssignmentsUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the task assignment to update',\n\t}),\n};\n\nmodule.exports = TaskAssignmentsUpdateCommand;\n"
  },
  {
    "path": "src/commands/tasks/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass TasksCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(TasksCreateCommand);\n\t\tlet options = {};\n\n\t\tif (flags.message) {\n\t\t\toptions.message = flags.message;\n\t\t}\n\t\tif (flags['due-at']) {\n\t\t\toptions.due_at = flags['due-at'];\n\t\t}\n\t\tif (flags['completion-rule']) {\n\t\t\toptions.completion_rule = flags['completion-rule'];\n\t\t}\n\n\t\tlet task = await this.client.tasks.create(args.fileID, options);\n\t\tawait this.output(task);\n\t}\n}\n\nTasksCreateCommand.description = 'Create a task on a file';\nTasksCreateCommand.examples = [\n\t'box tasks:create 11111 --message \"Please proofread this document\"',\n];\nTasksCreateCommand._endpoint = 'post_tasks';\n\nTasksCreateCommand.flags = {\n\t...BoxCommand.flags,\n\tmessage: Flags.string({ description: 'Message for task' }),\n\t'due-at': Flags.string({\n\t\tdescription:\n\t\t\t'When this task is due, use format 05h for 5 hours for example',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'id-only': Flags.boolean({\n\t\tdescription: 'Return only an ID to output from this command',\n\t}),\n\t'completion-rule': Flags.string({\n\t\tdescription:\n\t\t\t'Rule for how many assignees must complete the task to consider it completed',\n\t\toptions: ['all_assignees', 'any_assignee'],\n\t}),\n};\n\nTasksCreateCommand.args = {\n\tfileID: Args.string({\n\t\tname: 'fileID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the file to create a task on',\n\t}),\n};\n\nmodule.exports = TasksCreateCommand;\n"
  },
  {
    "path": "src/commands/tasks/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass TasksDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(TasksDeleteCommand);\n\n\t\tawait this.client.tasks.delete(args.id);\n\t\tthis.info(`Successfully deleted task ${args.id}`);\n\t}\n}\n\nTasksDeleteCommand.description = 'Delete a task';\nTasksDeleteCommand.examples = ['box tasks:delete 88888'];\nTasksDeleteCommand._endpoint = 'delete_tasks_id';\n\nTasksDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nTasksDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the task to delete',\n\t}),\n};\n\nmodule.exports = TasksDeleteCommand;\n"
  },
  {
    "path": "src/commands/tasks/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass TasksGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(TasksGetCommand);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet task = await this.client.tasks.get(args.id, options);\n\t\tawait this.output(task);\n\t}\n}\n\nTasksGetCommand.description = 'Get information about a task';\nTasksGetCommand.examples = ['box tasks:get 88888'];\nTasksGetCommand._endpoint = 'get_tasks_id';\n\nTasksGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nTasksGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the task to get',\n\t}),\n};\n\nmodule.exports = TasksGetCommand;\n"
  },
  {
    "path": "src/commands/tasks/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass TasksUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(TasksUpdateCommand);\n\t\tlet options = {};\n\n\t\tif (flags.message) {\n\t\t\toptions.message = flags.message;\n\t\t}\n\t\tif (flags['due-at']) {\n\t\t\toptions.due_at = flags['due-at'];\n\t\t}\n\t\tif (flags['completion-rule']) {\n\t\t\toptions.completion_rule = flags['completion-rule'];\n\t\t}\n\n\t\tlet task = await this.client.tasks.update(args.id, options);\n\t\tawait this.output(task);\n\t}\n}\n\nTasksUpdateCommand.description = 'Update a task on a file';\nTasksUpdateCommand.examples = ['box tasks:update 88888 --due-at 1w'];\nTasksUpdateCommand._endpoint = 'put_tasks_id';\n\nTasksUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\tmessage: Flags.string({ description: 'Message for task' }),\n\t'due-at': Flags.string({\n\t\tdescription:\n\t\t\t'When this task is due, use format 05h for 5 hours for example',\n\t\tparse: (input) => BoxCommand.normalizeDateString(input),\n\t}),\n\t'completion-rule': Flags.string({\n\t\tdescription:\n\t\t\t'Rule for how many assignees must complete the task to consider it completed',\n\t\toptions: ['all_assignees', 'any_assignee'],\n\t}),\n};\n\nTasksUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the task to update',\n\t}),\n};\n\nmodule.exports = TasksUpdateCommand;\n"
  },
  {
    "path": "src/commands/terms-of-service/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\n\nclass TermsOfServiceCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(TermsOfServiceCreateCommand);\n\n\t\tlet termsOfService = await this.client.termsOfService.create(\n\t\t\tflags.type,\n\t\t\tflags.status,\n\t\t\tflags.text\n\t\t);\n\t\tawait this.output(termsOfService);\n\t}\n}\n\nTermsOfServiceCreateCommand.description = 'Create a terms of service';\nTermsOfServiceCreateCommand.examples = [\n\t'box terms-of-service:create --type external --status enabled --text \"By using this service, you agree to....\"',\n];\nTermsOfServiceCreateCommand._endpoint = 'post_terms_of_services';\n\nTermsOfServiceCreateCommand.flags = {\n\t...BoxCommand.flags,\n\ttype: Flags.string({\n\t\tdescription: 'Type of terms of service',\n\t\trequired: true,\n\t\toptions: ['managed', 'external'],\n\t}),\n\tstatus: Flags.string({\n\t\tdescription: 'Status of the terms of service',\n\t\trequired: true,\n\t\toptions: ['enabled', 'disabled'],\n\t}),\n\ttext: Flags.string({\n\t\tdescription: 'Text for the terms of service',\n\t\trequired: true,\n\t}),\n};\n\nmodule.exports = TermsOfServiceCreateCommand;\n"
  },
  {
    "path": "src/commands/terms-of-service/get-user-status.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass TermsOfServiceGetUserStatusCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tTermsOfServiceGetUserStatusCommand\n\t\t);\n\t\tlet options = {};\n\n\t\tif (flags['user-id']) {\n\t\t\toptions.user_id = flags['user-id'];\n\t\t}\n\n\t\tlet tosStatus = await this.client.termsOfService.getUserStatus(\n\t\t\targs.tosID,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(tosStatus);\n\t}\n}\n\nTermsOfServiceGetUserStatusCommand.description =\n\t\"Get a user's status on a terms of service\";\nTermsOfServiceGetUserStatusCommand.examples = [\n\t'box terms-of-service:get-user-status 55555',\n];\nTermsOfServiceGetUserStatusCommand._endpoint =\n\t'get_terms_of_service_user_statuses';\n\nTermsOfServiceGetUserStatusCommand.flags = {\n\t...BoxCommand.flags,\n\t'user-id': Flags.string({\n\t\tdescription:\n\t\t\t'ID for a user to get status for; defaults to the current user ID',\n\t}),\n};\n\nTermsOfServiceGetUserStatusCommand.args = {\n\ttosID: Args.string({\n\t\tname: 'tosID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the terms of service to get user status for',\n\t}),\n};\n\nmodule.exports = TermsOfServiceGetUserStatusCommand;\n"
  },
  {
    "path": "src/commands/terms-of-service/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass TermsOfServiceGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(TermsOfServiceGetCommand);\n\n\t\tlet termsOfService = await this.client.termsOfService.get(args.id);\n\t\tawait this.output(termsOfService);\n\t}\n}\n\nTermsOfServiceGetCommand.description = 'Get information on a terms of service';\nTermsOfServiceGetCommand.examples = ['box terms-of-service:get 55555'];\nTermsOfServiceGetCommand._endpoint = 'get_terms_of_services_id';\n\nTermsOfServiceGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nTermsOfServiceGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID for the terms of service to get',\n\t}),\n};\n\nmodule.exports = TermsOfServiceGetCommand;\n"
  },
  {
    "path": "src/commands/terms-of-service/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\n\nclass TermsOfServiceListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(TermsOfServiceListCommand);\n\t\tlet options = {};\n\n\t\tif (flags.type) {\n\t\t\toptions.tos_type = flags.type;\n\t\t}\n\n\t\tlet termsOfService = await this.client.termsOfService.getAll(options);\n\t\tawait this.output(termsOfService);\n\t}\n}\n\nTermsOfServiceListCommand.description =\n\t'List terms of services for your enterprise';\nTermsOfServiceListCommand.examples = ['box terms-of-service'];\nTermsOfServiceListCommand._endpoint = 'get_terms_of_services';\n\nTermsOfServiceListCommand.flags = {\n\t...BoxCommand.flags,\n\ttype: Flags.string({\n\t\tdescription: 'Filter by terms of service type',\n\t\toptions: ['managed', 'external'],\n\t}),\n};\n\nmodule.exports = TermsOfServiceListCommand;\n"
  },
  {
    "path": "src/commands/terms-of-service/set-user-status.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst BoxCLIError = require('../../cli-error');\n\nclass TermsOfServiceSetUserStatusCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(\n\t\t\tTermsOfServiceSetUserStatusCommand\n\t\t);\n\t\tlet options = {};\n\n\t\tif (flags['user-id']) {\n\t\t\toptions.user_id = flags['user-id'];\n\t\t}\n\n\t\tlet status;\n\t\tif (flags.accept) {\n\t\t\tstatus = true;\n\t\t} else if (flags.reject) {\n\t\t\tstatus = false;\n\t\t} else {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Either the --accept or --reject flag must be passed'\n\t\t\t);\n\t\t}\n\n\t\tlet tosStatus = await this.client.termsOfService.setUserStatus(\n\t\t\targs.id,\n\t\t\tstatus,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(tosStatus);\n\t}\n}\n\nTermsOfServiceSetUserStatusCommand.description =\n\t\"Set a user's status on a terms of service with a terms of service Id\";\nTermsOfServiceSetUserStatusCommand.examples = [\n\t'box terms-of-service:set-user-status 55555 --accept',\n];\n\nTermsOfServiceSetUserStatusCommand.flags = {\n\t...BoxCommand.flags,\n\taccept: Flags.boolean({\n\t\tdescription: \"Set the user's status as accepted\",\n\t\texclusive: ['reject'],\n\t}),\n\treject: Flags.boolean({\n\t\tdescription: \"Set the user's status as rejected\",\n\t\texclusive: ['accept'],\n\t}),\n\t'user-id': Flags.string({\n\t\tdescription:\n\t\t\t'ID of the user to set status for; defaults to the current user',\n\t}),\n};\n\nTermsOfServiceSetUserStatusCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the terms of service to set the user status on',\n\t}),\n};\n\nmodule.exports = TermsOfServiceSetUserStatusCommand;\n"
  },
  {
    "path": "src/commands/terms-of-service/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass TermsOfServiceUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(TermsOfServiceUpdateCommand);\n\t\tlet options = {};\n\n\t\tif (flags.status) {\n\t\t\toptions.status = flags.status;\n\t\t}\n\t\tif (flags.text) {\n\t\t\toptions.text = flags.text;\n\t\t}\n\n\t\tlet termsOfService = await this.client.termsOfService.update(\n\t\t\targs.id,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(termsOfService);\n\t}\n}\n\nTermsOfServiceUpdateCommand.description = 'Update a terms of service';\nTermsOfServiceUpdateCommand.examples = [\n\t'box terms-of-service:update 55555 --status disabled',\n];\nTermsOfServiceUpdateCommand._endpoint = 'put_terms_of_services_id';\n\nTermsOfServiceUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\tstatus: Flags.string({\n\t\tdescription: 'Status of the terms of service',\n\t\toptions: ['enabled', 'disabled'],\n\t}),\n\ttext: Flags.string({ description: 'Text for the terms of service' }),\n};\n\nTermsOfServiceUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the terms of service to update',\n\t}),\n};\n\nmodule.exports = TermsOfServiceUpdateCommand;\n"
  },
  {
    "path": "src/commands/tokens/exchange.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass TokensExchangeCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(TokensExchangeCommand);\n\n\t\tlet client = this.client;\n\t\tif (flags.token) {\n\t\t\tclient = this.sdk.getBasicClient(flags.token);\n\t\t}\n\t\tif (flags['user-id']) {\n\t\t\tclient = this.sdk.getAppAuthClient('user', flags['user-id']);\n\t\t}\n\n\t\tlet resource = null;\n\t\tif (flags['file-id']) {\n\t\t\tresource = `https://api.box.com/2.0/files/${flags['file-id']}`;\n\t\t} else if (flags['folder-id']) {\n\t\t\tresource = `https://api.box.com/2.0/folders/${flags['folder-id']}`;\n\t\t}\n\n\t\tlet tokenInfo = await client.exchangeToken(\n\t\t\targs.scope.split(','),\n\t\t\tresource\n\t\t);\n\n\t\tthis.output(tokenInfo.accessToken);\n\t}\n}\n\nTokensExchangeCommand.description =\n\t'Get a token. Returns the service account token by default';\n\nTokensExchangeCommand.args = {\n\tscope: Args.string({\n\t\tname: 'scope',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription:\n\t\t\t'The scope(s) for the new token, separated by a comma if multiple are present',\n\t}),\n};\n\nTokensExchangeCommand.flags = {\n\t...BoxCommand.minFlags,\n\t'user-id': Flags.string({\n\t\tchar: 'u',\n\t\tdescription: 'Get a user token from a user ID',\n\t\texclusive: ['token'],\n\t}),\n\t'file-id': Flags.string({\n\t\tdescription: 'Scope the token to a specific file',\n\t\texclusive: ['folder-id'],\n\t}),\n\t'folder-id': Flags.string({\n\t\tdescription: 'Scope the token to a specific folder',\n\t\texclusive: ['file-id'],\n\t}),\n\ttoken: Flags.string({\n\t\tchar: 't',\n\t\tdescription: 'Specify the token to exchange',\n\t\texclusive: ['user-id'],\n\t}),\n};\n\nmodule.exports = TokensExchangeCommand;\n"
  },
  {
    "path": "src/commands/tokens/get.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\n\nclass TokensGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(TokensGetCommand);\n\t\tlet token;\n\n\t\ttoken = await (flags['user-id']\n\t\t\t? this.sdk.getAppUserTokens(flags['user-id'])\n\t\t\t: this.sdk.getEnterpriseAppAuthTokens());\n\t\tthis.output(token.accessToken);\n\t}\n}\n\nTokensGetCommand.description =\n\t'Generate a new access token. Returns a service account token for the default environment unless --user-id is specified.';\nTokensGetCommand.examples = [\n\t'box tokens:get',\n\t'box tokens:get --user-id 12345',\n];\n\nTokensGetCommand.flags = {\n\t...BoxCommand.minFlags,\n\t'user-id': Flags.string({\n\t\tchar: 'u',\n\t\tdescription: 'Generate a user token for the specified user ID',\n\t}),\n};\n\nmodule.exports = TokensGetCommand;\n"
  },
  {
    "path": "src/commands/tokens/revoke.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Args } = require('@oclif/core');\nconst chalk = require('chalk');\n\nclass TokensRevokeCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(TokensRevokeCommand);\n\n\t\tlet response = await this.sdk.revokeTokens(args.token);\n\n\t\tif (response.statusCode === 200) {\n\t\t\tthis.info(chalk`{green Token revoked.}`);\n\t\t} else {\n\t\t\tthis.info(\n\t\t\t\tchalk`{redBright Error revoking token!  ${response.body.error_description}}`\n\t\t\t);\n\t\t}\n\t}\n}\n\nTokensRevokeCommand.description =\n\t'Revoke a token.  The token will no longer be valid for making API calls.';\n\nTokensRevokeCommand.args = {\n\ttoken: Args.string({\n\t\tname: 'token',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The token to revoke',\n\t}),\n};\n\nTokensRevokeCommand.flags = {\n\t...BoxCommand.minFlags,\n};\n\nmodule.exports = TokensRevokeCommand;\n"
  },
  {
    "path": "src/commands/trash/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass TrashDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(TrashDeleteCommand);\n\n\t\tswitch (args.type) {\n\t\t\tcase 'file': {\n\t\t\t\tawait this.client.files.deletePermanently(args.id);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'folder': {\n\t\t\t\tawait this.client.folders.deletePermanently(args.id);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'web_link': {\n\t\t\t\tawait this.client.wrapWithDefaultHandler(this.client.del)(\n\t\t\t\t\t`/web_links/${args.id}/trash`\n\t\t\t\t);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// No default\n\t\t}\n\t\tthis.info(`Deleted item ${args.id}`);\n\t}\n}\n\nTrashDeleteCommand.description = 'Permanently delete an item';\nTrashDeleteCommand.examples = ['box trash:delete folder 22222'];\n\nTrashDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nTrashDeleteCommand.args = {\n\ttype: Args.string({\n\t\tname: 'type',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Type of the item to permanently delete',\n\t\toptions: ['file', 'folder', 'web_link'],\n\t}),\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the item to permanently delete',\n\t}),\n};\n\nmodule.exports = TrashDeleteCommand;\n"
  },
  {
    "path": "src/commands/trash/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass TrashGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(TrashGetCommand);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\t\tlet item;\n\t\tswitch (args.type) {\n\t\t\tcase 'file': {\n\t\t\t\titem = await this.client.files.getTrashedFile(args.id, options);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'folder': {\n\t\t\t\titem = await this.client.folders.getTrashedFolder(\n\t\t\t\t\targs.id,\n\t\t\t\t\toptions\n\t\t\t\t);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'web_link': {\n\t\t\t\titem = await this.client.wrapWithDefaultHandler(\n\t\t\t\t\tthis.client.get\n\t\t\t\t)(`/web_links/${args.id}/trash`, { qs: options });\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// No default\n\t\t}\n\t\tawait this.output(item);\n\t}\n}\n\nTrashGetCommand.description = 'Get information about an item in trash';\nTrashGetCommand.examples = ['box trash:get folder 22222'];\n\nTrashGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nTrashGetCommand.args = {\n\ttype: Args.string({\n\t\tname: 'type',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Type of the item to get',\n\t\toptions: ['file', 'folder', 'web_link'],\n\t}),\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the item to get',\n\t}),\n};\n\nmodule.exports = TrashGetCommand;\n"
  },
  {
    "path": "src/commands/trash/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass TrashListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(TrashListCommand);\n\t\tlet options = PaginationUtilities.forceMarkerPagination(flags);\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet trashedItems = await this.client.trash.get(options);\n\t\tawait this.output(trashedItems);\n\t}\n}\n\nTrashListCommand.aliases = ['trash:list'];\n\nTrashListCommand.description = 'List all items in trash';\nTrashListCommand.examples = ['box trash'];\nTrashListCommand._endpoint = 'get_folders_trash_items';\n\nTrashListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nmodule.exports = TrashListCommand;\n"
  },
  {
    "path": "src/commands/trash/restore.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass TrashRestoreCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(TrashRestoreCommand);\n\t\tlet options = {};\n\n\t\tif (flags.name) {\n\t\t\toptions.name = flags.name;\n\t\t}\n\t\tif (flags['parent-id']) {\n\t\t\toptions.parent = {\n\t\t\t\tid: flags['parent-id'],\n\t\t\t};\n\t\t}\n\t\tlet item;\n\t\tswitch (args.type) {\n\t\t\tcase 'file': {\n\t\t\t\titem = await this.client.files.restoreFromTrash(\n\t\t\t\t\targs.id,\n\t\t\t\t\toptions\n\t\t\t\t);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'folder': {\n\t\t\t\titem = await this.client.folders.restoreFromTrash(\n\t\t\t\t\targs.id,\n\t\t\t\t\toptions\n\t\t\t\t);\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase 'web_link': {\n\t\t\t\titem = await this.client.wrapWithDefaultHandler(\n\t\t\t\t\tthis.client.post\n\t\t\t\t)(`/web_links/${args.id}`, { body: options });\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// No default\n\t\t}\n\t\tawait this.output(item);\n\t}\n}\n\nTrashRestoreCommand.description = 'Restore an item from trash';\nTrashRestoreCommand.examples = ['box trash:restore folder 22222'];\n\nTrashRestoreCommand.flags = {\n\t...BoxCommand.flags,\n\tname: Flags.string({\n\t\tdescription: 'The new name for the item',\n\t}),\n\t'parent-id': Flags.string({\n\t\tdescription:\n\t\t\t'ID of a folder to restore the item to only when the original folder no longer exists',\n\t}),\n};\n\nTrashRestoreCommand.args = {\n\ttype: Args.string({\n\t\tname: 'type',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Type of the item to restore',\n\t\toptions: ['file', 'folder', 'web_link'],\n\t}),\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the item to restore',\n\t}),\n};\n\nmodule.exports = TrashRestoreCommand;\n"
  },
  {
    "path": "src/commands/update.js",
    "content": "'use strict';\nconst { sort } = require('semver');\nconst path = require('node:path');\nconst GitHubUpdater = require('../github-updater');\nconst UpdateCommand =\n\trequire('@oclif/plugin-update/lib/commands/update').default;\n\nclass GithubUpdatecommand extends UpdateCommand {\n\tasync run() {\n\t\tconst { printTable } = await import('@oclif/table');\n\t\tconst { flags } = await this.parse(UpdateCommand);\n\t\tconst updater = new GitHubUpdater(this.config);\n\t\tif (flags.available) {\n\t\t\tconst index = await updater.fetchVersionIndex();\n\t\t\tconst allVersions = sort(Object.keys(index)).reverse();\n\t\t\tconst localVersions = await updater.findLocalVersions();\n\n\t\t\tconst table = allVersions.map((version) => {\n\t\t\t\tconst location =\n\t\t\t\t\tlocalVersions.find((l) =>\n\t\t\t\t\t\tpath.basename(l).startsWith(version)\n\t\t\t\t\t) || index[version];\n\t\t\t\treturn { version, location };\n\t\t\t});\n\n\t\t\tprintTable({\n\t\t\t\tcolumns: [{ key: 'version' }, { key: 'location' }],\n\t\t\t\tdata: table,\n\t\t\t});\n\t\t\treturn;\n\t\t}\n\n\t\tupdater.runUpdate({\n\t\t\tautoUpdate: flags.autoupdate,\n\t\t\tforce: flags.force,\n\t\t\tversion: flags.interactive\n\t\t\t\t? await this.promptForVersion(updater)\n\t\t\t\t: flags.version,\n\t\t});\n\t}\n}\n\nGithubUpdatecommand.args = [];\nGithubUpdatecommand.examples = GithubUpdatecommand.examples.slice(1);\nGithubUpdatecommand.description = 'Update the BoxCLI using GitHub';\n\nmodule.exports = GithubUpdatecommand;\n"
  },
  {
    "path": "src/commands/users/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst BoxCLIError = require('../../cli-error');\n\nclass UsersCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(UsersCreateCommand);\n\t\tlet options = {};\n\t\tlet user;\n\n\t\tif (Object.hasOwn(flags, 'sync-enable')) {\n\t\t\toptions.is_sync_enabled = flags['sync-enable'];\n\t\t}\n\t\tif (flags['password-reset']) {\n\t\t\toptions.is_password_reset_required = true;\n\t\t}\n\t\tif (Object.hasOwn(flags, 'exempt-from-device-limits')) {\n\t\t\toptions.is_exempt_from_device_limits =\n\t\t\t\tflags['exempt-from-device-limits'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'exempt-from-2fa')) {\n\t\t\toptions.is_exempt_from_login_verification =\n\t\t\t\tflags['exempt-from-2fa'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'restrict-external-collab')) {\n\t\t\toptions.is_external_collab_restricted =\n\t\t\t\tflags['restrict-external-collab'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'can-see-managed-users')) {\n\t\t\toptions.can_see_managed_users = flags['can-see-managed-users'];\n\t\t}\n\t\tif (flags.role) {\n\t\t\toptions.role = flags.role;\n\t\t}\n\t\tif (flags.language) {\n\t\t\toptions.language = flags.language;\n\t\t}\n\t\tif (flags['job-title']) {\n\t\t\toptions.job_title = flags['job-title'];\n\t\t}\n\t\tif (flags['phone-number']) {\n\t\t\toptions.phone = flags['phone-number'];\n\t\t}\n\t\tif (flags.address) {\n\t\t\toptions.address = flags.address;\n\t\t}\n\t\tif (flags['disk-space']) {\n\t\t\toptions.space_amount = Number.parseInt(flags['disk-space'], 10);\n\t\t}\n\t\tif (flags.status) {\n\t\t\toptions.status = flags.status;\n\t\t}\n\t\tif (flags.timezone) {\n\t\t\toptions.timezone = flags.timezone;\n\t\t}\n\t\tif (flags['external-id']) {\n\t\t\toptions.external_app_user_id = flags['external-id'];\n\t\t}\n\t\tif (flags['tracking-codes']) {\n\t\t\toptions.tracking_codes = flags['tracking-codes'];\n\t\t}\n\n\t\tif (flags['app-user']) {\n\t\t\tuser = await this.client.enterprise.addAppUser(args.name, options);\n\t\t} else if (args.login) {\n\t\t\tuser = await this.client.enterprise.addUser(\n\t\t\t\targs.login,\n\t\t\t\targs.name,\n\t\t\t\toptions\n\t\t\t);\n\t\t} else {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t'Either the login argument or the --app-user flag is required'\n\t\t\t);\n\t\t}\n\t\tawait this.output(user);\n\t}\n}\n\nUsersCreateCommand.description = 'Create a new Box User';\nUsersCreateCommand.examples = ['box users:create \"John Doe\" jdoe@example.com'];\nUsersCreateCommand._endpoint = 'post_users';\n\nUsersCreateCommand.flags = {\n\t...BoxCommand.flags,\n\t'app-user': Flags.boolean({\n\t\tdescription: 'Set this user as an app user',\n\t}),\n\t'external-id': Flags.string({\n\t\tdescription: 'External ID for app users',\n\t\tdependsOn: ['app-user'],\n\t}),\n\t'id-only': Flags.boolean({\n\t\tdescription: 'Return only an ID to output from this command',\n\t}),\n\t'sync-enable': Flags.boolean({\n\t\tdescription: 'Enable Box Sync for this user',\n\t\texclusive: ['sync-disable'],\n\t\tallowNo: true,\n\t}),\n\t'exempt-from-device-limits': Flags.boolean({\n\t\tdescription: 'Exempt user from device limits',\n\t\tallowNo: true,\n\t}),\n\t'exempt-from-2fa': Flags.boolean({\n\t\tdescription: 'Exempt user from two-factor auth',\n\t\tallowNo: true,\n\t}),\n\t'restrict-external-collab': Flags.boolean({\n\t\tdescription: 'Restrict user from external collaboration',\n\t\tallowNo: true,\n\t}),\n\t'can-see-managed-users': Flags.boolean({\n\t\tdescription: 'User can see managed users',\n\t\tallowNo: true,\n\t}),\n\t'password-reset': Flags.boolean({\n\t\tdescription: 'Force the user to reset password',\n\t}),\n\trole: Flags.string({\n\t\tchar: 'r',\n\t\tdescription: 'Role of user. Enter user or coadmin',\n\t\toptions: ['user', 'coadmin'],\n\t}),\n\tlanguage: Flags.string({\n\t\tchar: 'l',\n\t\tdescription:\n\t\t\t'Language of the user (ISO 639-1 Language Code). https://developer.box.com/v2.0/docs/api-language-codes',\n\t}),\n\t'job-title': Flags.string({\n\t\tchar: 'j',\n\t\tdescription: 'Job title of the user',\n\t}),\n\t'phone-number': Flags.string({\n\t\tchar: 'p',\n\t\tdescription: 'Phone number of the user',\n\t}),\n\taddress: Flags.string({\n\t\tchar: 'a',\n\t\tdescription: 'Address of the user',\n\t}),\n\t'disk-space': Flags.string({\n\t\tchar: 'd',\n\t\tdescription:\n\t\t\t\"User's available storage in bytes. Value of -1 grants unlimited storage\",\n\t}),\n\tstatus: Flags.string({\n\t\tchar: 'S',\n\t\tdescription: 'User status',\n\t\toptions: [\n\t\t\t'active',\n\t\t\t'inactive',\n\t\t\t'cannot_delete_edit',\n\t\t\t'cannot_delete_edit_upload',\n\t\t],\n\t}),\n\ttimezone: Flags.string({\n\t\tdescription:\n\t\t\t\"The user's timezone. Input format follows tz database timezones\",\n\t}),\n\t'tracking-codes': Flags.string({\n\t\tdescription:\n\t\t\t'Comma-separated list of key-value pairs to associate with the user. Format is name=value,name=value',\n\t\tparse: (input) =>\n\t\t\tinput.split(',').map((pair) => {\n\t\t\t\tconst [name, value] = pair.split('=');\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'tracking_code',\n\t\t\t\t\tname,\n\t\t\t\t\tvalue,\n\t\t\t\t};\n\t\t\t}),\n\t}),\n};\n\nUsersCreateCommand.args = {\n\tname: Args.string({\n\t\tname: 'name',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: \"The user's name\",\n\t}),\n\tlogin: Args.string({\n\t\tname: 'login',\n\t\trequired: false,\n\t\thidden: false,\n\t\tdescription:\n\t\t\t\"The user's email address, not required when creating app users\",\n\t}),\n};\n\nmodule.exports = UsersCreateCommand;\n"
  },
  {
    "path": "src/commands/users/delete.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass UsersDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(UsersDeleteCommand);\n\t\tlet options = {};\n\n\t\tif (Object.hasOwn(flags, 'notify')) {\n\t\t\toptions.notify = flags.notify;\n\t\t}\n\t\tif (Object.hasOwn(flags, 'force')) {\n\t\t\toptions.force = flags.force;\n\t\t}\n\n\t\tawait this.client.users.delete(args.id, options);\n\t\tthis.info(`Deleted user ${args.id}`);\n\t}\n}\n\nUsersDeleteCommand.description = 'Delete a Box User';\nUsersDeleteCommand.examples = ['box users:delete 33333'];\nUsersDeleteCommand._endpoint = 'delete_users_id';\n\nUsersDeleteCommand.flags = {\n\t...BoxCommand.flags,\n\tnotify: Flags.boolean({\n\t\tdescription: 'The user should be notified',\n\t\tallowNo: true,\n\t}),\n\tforce: Flags.boolean({\n\t\tchar: 'f',\n\t\tdescription: 'Delete user even if they own files',\n\t}),\n};\n\nUsersDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'User ID to delete',\n\t}),\n};\n\nmodule.exports = UsersDeleteCommand;\n"
  },
  {
    "path": "src/commands/users/email-aliases/add.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass UsersAddEmailAliasCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(UsersAddEmailAliasCommand);\n\n\t\tlet options = {};\n\n\t\tif (Object.hasOwn(flags, 'confirm')) {\n\t\t\toptions.is_confirmed = flags.confirm;\n\t\t}\n\n\t\tlet alias = await this.client.users.addEmailAlias(\n\t\t\targs.userID,\n\t\t\targs.email,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(alias);\n\t}\n}\n\nUsersAddEmailAliasCommand.aliases = ['users:add-email-alias'];\n\nUsersAddEmailAliasCommand.description = 'Add a new email alias to a user';\nUsersAddEmailAliasCommand.examples = [\n\t'box users:email-aliases:add 33333 user+alias@example.com',\n];\nUsersAddEmailAliasCommand._endpoint = 'post_users_id_email_aliases';\n\nUsersAddEmailAliasCommand.flags = {\n\t...BoxCommand.flags,\n\tconfirm: Flags.boolean({\n\t\tallowNo: true,\n\t\tdescription:\n\t\t\t'Whether or not to confirm the email alias.  Only Admins may automatically confirm an alias.',\n\t}),\n};\n\nUsersAddEmailAliasCommand.args = {\n\tuserID: Args.string({\n\t\tname: 'userID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'User ID to add email alias',\n\t}),\n\temail: Args.string({\n\t\tname: 'email',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Email to add as alias',\n\t}),\n};\n\nmodule.exports = UsersAddEmailAliasCommand;\n"
  },
  {
    "path": "src/commands/users/email-aliases/index.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass UsersGetEmailAliasesCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(UsersGetEmailAliasesCommand);\n\n\t\tlet emailAliases = await this.client.users.getEmailAliases(args.userID);\n\t\tawait this.output(emailAliases);\n\t}\n}\n\nUsersGetEmailAliasesCommand.aliases = ['users:get-email-aliases'];\n\nUsersGetEmailAliasesCommand.description = 'Get all Email Aliases for a User';\nUsersGetEmailAliasesCommand.examples = ['box users:email-aliases 33333'];\nUsersGetEmailAliasesCommand._endpoint = 'get_users_id_email_aliases';\n\nUsersGetEmailAliasesCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nUsersGetEmailAliasesCommand.args = {\n\tuserID: Args.string({\n\t\tname: 'userID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'User ID to get email aliases for',\n\t}),\n};\n\nmodule.exports = UsersGetEmailAliasesCommand;\n"
  },
  {
    "path": "src/commands/users/email-aliases/remove.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../../box-command');\n\nclass UsersDeleteEmailAliasCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(UsersDeleteEmailAliasCommand);\n\n\t\tawait this.client.users.removeEmailAlias(args.userID, args.aliasID);\n\t\tthis.info(`Removed alias ${args.aliasID} from user ${args.userID}`);\n\t}\n}\n\nUsersDeleteEmailAliasCommand.aliases = ['users:delete-email-alias'];\n\nUsersDeleteEmailAliasCommand.description = 'Delete an email alias from a user';\nUsersDeleteEmailAliasCommand.examples = [\n\t'box users:email-aliases:remove 33333 12345',\n];\nUsersDeleteEmailAliasCommand._endpoint = 'delete_users_id_email_aliases_id';\n\nUsersDeleteEmailAliasCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nUsersDeleteEmailAliasCommand.args = {\n\tuserID: Args.string({\n\t\tname: 'userID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'User ID to get email aliases',\n\t}),\n\taliasID: Args.string({\n\t\tname: 'aliasID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'The ID of the email alias to delete',\n\t}),\n};\n\nmodule.exports = UsersDeleteEmailAliasCommand;\n"
  },
  {
    "path": "src/commands/users/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass UsersGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(UsersGetCommand);\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet user = await this.client.users.get(args.id, options);\n\t\tawait this.output(user);\n\t}\n}\n\nUsersGetCommand.description = 'Get information about a Box user';\nUsersGetCommand.examples = ['box users:get 33333'];\nUsersGetCommand._endpoint = 'get_users_id';\n\nUsersGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nUsersGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: false,\n\t\thidden: false,\n\t\tdefault: 'me',\n\t\tdescription: 'ID of the user to get; defaults to the current user',\n\t}),\n};\n\nmodule.exports = UsersGetCommand;\n"
  },
  {
    "path": "src/commands/users/groups.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass UsersListGroupsCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(UsersListGroupsCommand);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tlet groups = await this.client.users.getGroupMemberships(\n\t\t\targs.id,\n\t\t\toptions\n\t\t);\n\t\tawait this.output(groups);\n\t}\n}\n\nUsersListGroupsCommand.aliases = ['users:list-groups'];\n\nUsersListGroupsCommand.description = 'List groups a user belongs to';\nUsersListGroupsCommand.examples = ['box users:groups 33333'];\nUsersListGroupsCommand._endpoint = 'get_users_id_memberships';\n\nUsersListGroupsCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nUsersListGroupsCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the user to get groups for',\n\t}),\n};\n\nmodule.exports = UsersListGroupsCommand;\n"
  },
  {
    "path": "src/commands/users/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\nconst UserModule = require('../../modules/user');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass UsersListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(UsersListCommand);\n\t\tlet options = PaginationUtilities.forceMarkerPagination(flags);\n\t\tflags.limit = options.limit;\n\t\tflags.usemarker = options.usemarker;\n\n\t\tlet userModule = new UserModule(this.client);\n\t\tlet users = await userModule.listUsers(flags);\n\t\tawait this.output(users);\n\t}\n}\n\nUsersListCommand.aliases = ['users:list'];\n\nUsersListCommand.description = 'List all Box users';\nUsersListCommand.examples = ['box users'];\nUsersListCommand._endpoint = 'get_users';\n\nUsersListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n\t'managed-users': Flags.boolean({\n\t\tchar: 'm',\n\t\tdescription: 'Limit results to managed users only',\n\t\texclusive: ['app-users', 'all-users'],\n\t}),\n\t'app-users': Flags.boolean({\n\t\tdescription: 'Limit results to app users only',\n\t\texclusive: ['managed-users', 'all-users', 'filter'],\n\t}),\n\t'external-users': Flags.boolean({\n\t\tchar: 'e',\n\t\tdescription: 'Limit results to external users only',\n\t\texclusive: ['managed-users', 'all-users'],\n\t}),\n\t'all-users': Flags.boolean({\n\t\tchar: 'a',\n\t\tdescription: 'Results from all users',\n\t\texclusive: ['external-users', 'managed-users', 'app-users'],\n\t}),\n\tfilter: Flags.string({\n\t\tdescription:\n\t\t\t'Search term to filter users on; matches prefixes of user name and login fields',\n\t\texclusive: ['app-users'],\n\t}),\n};\n\nmodule.exports = UsersListCommand;\n"
  },
  {
    "path": "src/commands/users/invite.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass UsersInviteUserCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(UsersInviteUserCommand);\n\n\t\tlet user = await this.client.enterprise.inviteUser(\n\t\t\targs.enterpriseID,\n\t\t\targs.email\n\t\t);\n\t\tawait this.output(user);\n\t}\n}\n\nUsersInviteUserCommand.aliases = ['users:invite-user'];\n\nUsersInviteUserCommand.description =\n\t'Invite an Existing Box User to Your Enterprise';\nUsersInviteUserCommand.examples = ['box users:invite user@example.com 12345'];\nUsersInviteUserCommand._endpoint = 'post_invites';\n\nUsersInviteUserCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nUsersInviteUserCommand.args = {\n\temail: Args.string({\n\t\tname: 'email',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Email address of the user to invite',\n\t}),\n\tenterpriseID: Args.string({\n\t\tname: 'enterpriseID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the Enterprise to invite the user to',\n\t}),\n};\n\nmodule.exports = UsersInviteUserCommand;\n"
  },
  {
    "path": "src/commands/users/search.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst UsersListCommand = require('.'); // This points to ./index.js\nconst UserModule = require('../../modules/user');\nconst _ = require('lodash');\nconst { Args } = require('@oclif/core');\n\nclass UsersSearchCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(UsersSearchCommand);\n\n\t\tflags.filter = args.name;\n\n\t\tlet userModule = new UserModule(this.client);\n\t\tlet users = await userModule.listUsers(flags);\n\t\tawait this.output(users);\n\t}\n}\n\nUsersSearchCommand.description = 'Search for Box users';\nUsersSearchCommand.examples = ['box users:search \"John Doe\"'];\n\nUsersSearchCommand.flags = {\n\t...BoxCommand.flags,\n\t..._.pick(UsersListCommand.flags, [\n\t\t'managed-users',\n\t\t'external-users',\n\t\t'all-users',\n\t]),\n};\n\nUsersSearchCommand.args = {\n\tname: Args.string({\n\t\tname: 'name',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Name of user to search for',\n\t}),\n};\n\nmodule.exports = UsersSearchCommand;\n"
  },
  {
    "path": "src/commands/users/terminate-session.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags } = require('@oclif/core');\n\nclass UsersTerminateSessionCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(UsersTerminateSessionCommand);\n\n\t\tif (!flags['user-ids'] && !flags['user-logins']) {\n\t\t\tthrow new Error('You must specify at least one user ID or login');\n\t\t}\n\t\tlet response = await this.client.users.terminateSession({\n\t\t\tuser_ids: flags['user-ids'],\n\t\t\tuser_logins: flags['user-logins'],\n\t\t});\n\t\tawait this.output(response);\n\t}\n}\n\nUsersTerminateSessionCommand.description =\n\t\"Validates the roles and permissions of the user, and creates asynchronous jobs to terminate the user's sessions.\";\nUsersTerminateSessionCommand.examples = [\n\t'box users:terminate-session --user-ids 123 345 --user-logins abc@example.com def@example.com',\n];\nUsersTerminateSessionCommand._endpoint = 'post_users_terminate_sessions';\n\nUsersTerminateSessionCommand.flags = {\n\t...BoxCommand.flags,\n\t'user-ids': Flags.string({\n\t\tdescription: 'A list of user IDs',\n\t\tmultiple: true,\n\t}),\n\t'user-logins': Flags.string({\n\t\tdescription: 'A list of user logins',\n\t\tmultiple: true,\n\t}),\n};\n\nmodule.exports = UsersTerminateSessionCommand;\n"
  },
  {
    "path": "src/commands/users/transfer-content.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass UsersMoveRootContentCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(UsersMoveRootContentCommand);\n\t\tlet parameters = {\n\t\t\tbody: {\n\t\t\t\towned_by: {\n\t\t\t\t\tid: args.newUserID,\n\t\t\t\t},\n\t\t\t},\n\t\t\tqs: {},\n\t\t};\n\n\t\tif (Object.hasOwn(flags, 'notify')) {\n\t\t\tparameters.qs.notify = flags.notify;\n\t\t}\n\n\t\t// @TODO (2018-07-07): Should implement this using the Node SDK. Existing this.client.enterprise.transferUserContent() does not allow the notify option to be passed\n\t\tlet movedFolder = await this.client.wrapWithDefaultHandler(\n\t\t\tthis.client.put\n\t\t)(`/users/${args.userID}/folders/0`, parameters);\n\t\tawait this.output(movedFolder);\n\t}\n}\n\nUsersMoveRootContentCommand.aliases = ['users:move-root-content'];\n\nUsersMoveRootContentCommand.description =\n\t\"Move a user's root content to another user\";\nUsersMoveRootContentCommand.examples = [\n\t'box users:transfer-content 33333 44444',\n];\nUsersMoveRootContentCommand._endpoint = 'put_users_id_folders_id';\n\nUsersMoveRootContentCommand.flags = {\n\t...BoxCommand.flags,\n\tnotify: Flags.boolean({\n\t\tdescription: 'Notify the user that their content has been moved',\n\t\tallowNo: true,\n\t}),\n};\n\nUsersMoveRootContentCommand.args = {\n\tuserID: Args.string({\n\t\tname: 'userID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'User whose content should be moved',\n\t}),\n\tnewUserID: Args.string({\n\t\tname: 'newUserID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'User to whom the content should be moved',\n\t}),\n};\n\nmodule.exports = UsersMoveRootContentCommand;\n"
  },
  {
    "path": "src/commands/users/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass UsersUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(UsersUpdateCommand);\n\t\tlet updates = {};\n\n\t\tif (Object.hasOwn(flags, 'sync-enable')) {\n\t\t\tupdates.is_sync_enabled = flags['sync-enable'];\n\t\t}\n\t\tif (flags['password-reset']) {\n\t\t\tupdates.is_password_reset_required = true;\n\t\t}\n\t\tif (Object.hasOwn(flags, 'exempt-from-device-limits')) {\n\t\t\tupdates.is_exempt_from_device_limits =\n\t\t\t\tflags['exempt-from-device-limits'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'exempt-from-2fa')) {\n\t\t\tupdates.is_exempt_from_login_verification =\n\t\t\t\tflags['exempt-from-2fa'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'restrict-external-collab')) {\n\t\t\tupdates.is_external_collab_restricted =\n\t\t\t\tflags['restrict-external-collab'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'can-see-managed-users')) {\n\t\t\tupdates.can_see_managed_users = flags['can-see-managed-users'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'notification-email')) {\n\t\t\tupdates.notification_email =\n\t\t\t\tflags['notification-email'] === ''\n\t\t\t\t\t? null\n\t\t\t\t\t: {\n\t\t\t\t\t\t\temail: flags['notification-email'],\n\t\t\t\t\t\t};\n\t\t}\n\t\tif (flags.role) {\n\t\t\tupdates.role = flags.role;\n\t\t}\n\t\tif (flags.language) {\n\t\t\tupdates.language = flags.language;\n\t\t}\n\t\tif (flags['job-title']) {\n\t\t\tupdates.job_title = flags['job-title'];\n\t\t}\n\t\tif (flags['phone-number']) {\n\t\t\tupdates.phone = flags['phone-number'];\n\t\t}\n\t\tif (flags.address) {\n\t\t\tupdates.address = flags.address;\n\t\t}\n\t\tif (flags['disk-space']) {\n\t\t\tupdates.space_amount = Number.parseInt(flags['disk-space'], 10);\n\t\t}\n\t\tif (flags.status) {\n\t\t\tupdates.status = flags.status;\n\t\t}\n\t\tif (flags.timezone) {\n\t\t\tupdates.timezone = flags.timezone;\n\t\t}\n\t\tif (flags.remove) {\n\t\t\tupdates.enterprise = null;\n\t\t}\n\t\tif (flags.login) {\n\t\t\tupdates.login = flags.login;\n\t\t}\n\t\tif (flags.name) {\n\t\t\tupdates.name = flags.name;\n\t\t}\n\t\tif (flags['external-id']) {\n\t\t\tupdates.external_app_user_id = flags['external-id'];\n\t\t}\n\t\tif (flags['tracking-codes']) {\n\t\t\tupdates.tracking_codes = flags['tracking-codes'];\n\t\t}\n\n\t\tlet user = await this.client.users.update(args.id, updates);\n\t\tawait this.output(user);\n\t}\n}\n\nUsersUpdateCommand.description = 'Update a Box User';\nUsersUpdateCommand.examples = ['box users:update 33333 --status inactive'];\nUsersUpdateCommand._endpoint = 'put_users_id';\n\nUsersUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\tremove: Flags.boolean({\n\t\tdescription:\n\t\t\t'Remove the user from the enterprise, convert to free account',\n\t}),\n\tname: Flags.string({\n\t\tchar: 'n',\n\t\tdescription: \"Set the user's name\",\n\t}),\n\t'sync-enable': Flags.boolean({\n\t\tdescription: 'Enable Box Sync for this user',\n\t\tallowNo: true,\n\t}),\n\t'exempt-from-device-limits': Flags.boolean({\n\t\tdescription: 'Exempt user from device limits',\n\t\tallowNo: true,\n\t}),\n\t'exempt-from-2fa': Flags.boolean({\n\t\tdescription: 'Exempt user from two-factor auth',\n\t\tallowNo: true,\n\t}),\n\t'restrict-external-collab': Flags.boolean({\n\t\tdescription: 'Restrict user from external collaboration',\n\t\tallowNo: true,\n\t}),\n\t'can-see-managed-users': Flags.boolean({\n\t\tdescription: 'User can see managed users',\n\t\tallowNo: true,\n\t}),\n\t'password-reset': Flags.boolean({\n\t\tdescription: 'Force the user to reset password',\n\t}),\n\trole: Flags.string({\n\t\tchar: 'r',\n\t\tdescription: 'Role of user. Enter user or coadmin',\n\t\toptions: ['user', 'coadmin'],\n\t}),\n\tlanguage: Flags.string({\n\t\tchar: 'l',\n\t\tdescription:\n\t\t\t'Language of the user (ISO 639-1 Language Code). https://developer.box.com/v2.0/docs/api-language-codes',\n\t}),\n\t'job-title': Flags.string({\n\t\tchar: 'j',\n\t\tdescription: 'Job title of the user',\n\t}),\n\t'phone-number': Flags.string({\n\t\tchar: 'p',\n\t\tdescription: 'Phone number of the user',\n\t}),\n\taddress: Flags.string({\n\t\tchar: 'a',\n\t\tdescription: 'Address of the user',\n\t}),\n\t'disk-space': Flags.string({\n\t\tchar: 'd',\n\t\tdescription:\n\t\t\t\"User's available storage in bytes. Value of -1 grants unlimited storage\",\n\t}),\n\tstatus: Flags.string({\n\t\tchar: 'S',\n\t\tdescription:\n\t\t\t'User status. Enter active, inactive, cannot_delete_edit, or cannot_delete_edit_upload',\n\t\toptions: [\n\t\t\t'active',\n\t\t\t'inactive',\n\t\t\t'cannot_delete_edit',\n\t\t\t'cannot_delete_edit_upload',\n\t\t],\n\t}),\n\ttimezone: Flags.string({\n\t\tdescription:\n\t\t\t\"The user's timezone. Input format follows tz database timezones\",\n\t}),\n\tlogin: Flags.string({\n\t\tdescription:\n\t\t\t\"Change the user's primary email address used for logging into Box \",\n\t}),\n\t'external-id': Flags.string({\n\t\tdescription: 'External ID for app users',\n\t}),\n\t'tracking-codes': Flags.string({\n\t\tdescription:\n\t\t\t'Comma-separated list of key-value pairs to associate with the user. Format is name=value,name=value',\n\t\tparse: (input) =>\n\t\t\tinput.split(',').map((pair) => {\n\t\t\t\tconst [name, value] = pair.split('=');\n\t\t\t\treturn {\n\t\t\t\t\ttype: 'tracking_code',\n\t\t\t\t\tname,\n\t\t\t\t\tvalue,\n\t\t\t\t};\n\t\t\t}),\n\t}),\n\t'notification-email': Flags.string({\n\t\tdescription:\n\t\t\t'Notification email address for the user, set to empty string to remove',\n\t}),\n};\n\nUsersUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'User ID to update',\n\t}),\n};\n\nmodule.exports = UsersUpdateCommand;\n"
  },
  {
    "path": "src/commands/watermarking/apply.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass WatermarkingApplyCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(WatermarkingApplyCommand);\n\t\tlet watermark;\n\n\t\tif (args.itemType === 'file') {\n\t\t\twatermark = await this.client.files.applyWatermark(args.itemID);\n\t\t} else if (args.itemType === 'folder') {\n\t\t\twatermark = await this.client.folders.applyWatermark(args.itemID);\n\t\t}\n\t\tawait this.output(watermark);\n\t}\n}\n\nWatermarkingApplyCommand.description = 'Apply a watermark on an item';\nWatermarkingApplyCommand.examples = ['box watermarking:apply folder 22222'];\n\nWatermarkingApplyCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nWatermarkingApplyCommand.args = {\n\titemType: Args.string({\n\t\tname: 'itemType',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Type of item to apply a watermark to',\n\t\toptions: ['file', 'folder'],\n\t}),\n\titemID: Args.string({\n\t\tname: 'itemID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the item to apply a watermark to',\n\t}),\n};\n\nmodule.exports = WatermarkingApplyCommand;\n"
  },
  {
    "path": "src/commands/watermarking/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass WatermarkingGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(WatermarkingGetCommand);\n\t\tlet watermark;\n\n\t\tif (args.itemType === 'file') {\n\t\t\twatermark = await this.client.files.getWatermark(args.itemID);\n\t\t} else if (args.itemType === 'folder') {\n\t\t\twatermark = await this.client.folders.getWatermark(args.itemID);\n\t\t}\n\n\t\t// Node SDK has inconsistent output, so we wrap this to provide a\n\t\t// consistent interface with watermarking:apply\n\t\tawait this.output({ watermark });\n\t}\n}\n\nWatermarkingGetCommand.description = 'Get the watermark on an item';\nWatermarkingGetCommand.examples = ['box watermarking:get folder 22222'];\n\nWatermarkingGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nWatermarkingGetCommand.args = {\n\titemType: Args.string({\n\t\tname: 'itemType',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Type of item to get watermark for',\n\t\toptions: ['file', 'folder'],\n\t}),\n\titemID: Args.string({\n\t\tname: 'itemID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the item to get watermark for',\n\t}),\n};\n\nmodule.exports = WatermarkingGetCommand;\n"
  },
  {
    "path": "src/commands/watermarking/remove.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass WatermarkingRemoveCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(WatermarkingRemoveCommand);\n\n\t\tif (args.itemType === 'file') {\n\t\t\tawait this.client.files.removeWatermark(args.itemID);\n\t\t} else if (args.itemType === 'folder') {\n\t\t\tawait this.client.folders.removeWatermark(args.itemID);\n\t\t}\n\t\tthis.info(`Removed watermark for ${args.itemType} ${args.itemID}`);\n\t}\n}\n\nWatermarkingRemoveCommand.description = 'Remove a watermark from an item';\nWatermarkingRemoveCommand.examples = ['box watermarking:remove folder 22222'];\n\nWatermarkingRemoveCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nWatermarkingRemoveCommand.args = {\n\titemType: Args.string({\n\t\tname: 'itemType',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Type of item to remove watermark from',\n\t\toptions: ['file', 'folder'],\n\t}),\n\titemID: Args.string({\n\t\tname: 'itemID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the item to remove watermark from',\n\t}),\n};\n\nmodule.exports = WatermarkingRemoveCommand;\n"
  },
  {
    "path": "src/commands/web-links/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass WebLinksCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(WebLinksCreateCommand);\n\t\tlet options = {};\n\n\t\tif (flags.description) {\n\t\t\toptions.description = flags.description;\n\t\t}\n\t\tif (flags.name) {\n\t\t\toptions.name = flags.name;\n\t\t}\n\n\t\tlet weblink = await this.client.weblinks.create(\n\t\t\targs.url,\n\t\t\tflags['parent-id'],\n\t\t\toptions\n\t\t);\n\t\tawait this.output(weblink);\n\t}\n}\n\nWebLinksCreateCommand.description = 'Create a new web link';\nWebLinksCreateCommand.examples = [\n\t'box web-links:create http://example.com --parent-id 0',\n];\nWebLinksCreateCommand._endpoint = 'post_web_links';\n\nWebLinksCreateCommand.flags = {\n\t...BoxCommand.flags,\n\tdescription: Flags.string({\n\t\tchar: 'd',\n\t\tdescription: 'Description of the web link',\n\t\tparse: utilities.unescapeSlashes,\n\t}),\n\tname: Flags.string({\n\t\tchar: 'n',\n\t\tdescription: 'Name of the web link. Defaults to the URL if not set',\n\t}),\n\t'parent-id': Flags.string({\n\t\trequired: true,\n\t\tdescription: 'ID of the folder to create the web link in',\n\t}),\n};\n\nWebLinksCreateCommand.args = {\n\turl: Args.string({\n\t\tname: 'url',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription:\n\t\t\t'The URL the web link points to. Must start with \"http://\" or \"https://\"',\n\t}),\n};\n\nmodule.exports = WebLinksCreateCommand;\n"
  },
  {
    "path": "src/commands/web-links/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass WebLinksDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(WebLinksDeleteCommand);\n\n\t\tawait this.client.weblinks.delete(args.id);\n\t\tthis.info(`Deleted weblink ${args.id}`);\n\t}\n}\n\nWebLinksDeleteCommand.description = 'Delete a web link';\nWebLinksDeleteCommand.examples = ['box web-links:delete 12345'];\nWebLinksDeleteCommand._endpoint = 'delete_web_links_id';\n\nWebLinksDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nWebLinksDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the web link to delete',\n\t}),\n};\n\nmodule.exports = WebLinksDeleteCommand;\n"
  },
  {
    "path": "src/commands/web-links/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass WebLinksGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(WebLinksGetCommand);\n\n\t\tlet weblink = await this.client.weblinks.get(args.id);\n\t\tawait this.output(weblink);\n\t}\n}\n\nWebLinksGetCommand.description = 'Get information about a web link';\nWebLinksGetCommand.examples = ['box web-links:get 12345'];\nWebLinksGetCommand._endpoint = 'get_web_links_id';\n\nWebLinksGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nWebLinksGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the web link to get',\n\t}),\n};\n\nmodule.exports = WebLinksGetCommand;\n"
  },
  {
    "path": "src/commands/web-links/move.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass WebLinksMoveCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(WebLinksMoveCommand);\n\t\tlet updates = { parent: { id: args.parentID } };\n\n\t\tlet weblink = await this.client.weblinks.update(args.id, updates);\n\t\tawait this.output(weblink);\n\t}\n}\n\nWebLinksMoveCommand.description = 'Move a web link';\nWebLinksMoveCommand.examples = ['box web-links:move 12345 22222'];\nWebLinksMoveCommand._endpoint = 'put_web_links_id move';\n\nWebLinksMoveCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nWebLinksMoveCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the web link to move',\n\t}),\n\tparentID: Args.string({\n\t\tname: 'parentID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the parent folder to move the web link into',\n\t}),\n};\n\nmodule.exports = WebLinksMoveCommand;\n"
  },
  {
    "path": "src/commands/web-links/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\nconst utilities = require('../../util');\n\nclass WebLinksUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(WebLinksUpdateCommand);\n\t\tlet updates = {};\n\n\t\tif (flags.description) {\n\t\t\tupdates.description = flags.description;\n\t\t}\n\t\tif (flags.name) {\n\t\t\tupdates.name = flags.name;\n\t\t}\n\t\tif (flags.url) {\n\t\t\tupdates.url = flags.url;\n\t\t}\n\n\t\tlet weblink = await this.client.weblinks.update(args.id, updates);\n\t\tawait this.output(weblink);\n\t}\n}\n\nWebLinksUpdateCommand.description = 'Update a web link';\nWebLinksUpdateCommand.examples = [\n\t'box web-links:update 12345 --name \"Example Site\"',\n];\nWebLinksUpdateCommand._endpoint = 'put_web_links_id';\n\nWebLinksUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\tdescription: Flags.string({\n\t\tchar: 'd',\n\t\tdescription: 'Description of the web link',\n\t\tparse: utilities.unescapeSlashes,\n\t}),\n\tname: Flags.string({\n\t\tchar: 'n',\n\t\tdescription: 'Name of the web link',\n\t}),\n\turl: Flags.string({\n\t\tchar: 'u',\n\t\tdescription:\n\t\t\t'The URL the web link points to. Must start with \"http://\" or \"https://\"',\n\t}),\n};\n\nWebLinksUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the web link to update',\n\t}),\n};\n\nmodule.exports = WebLinksUpdateCommand;\n"
  },
  {
    "path": "src/commands/webhooks/create.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass WebhooksCreateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(WebhooksCreateCommand);\n\n\t\tlet triggers = flags.triggers.split(',');\n\n\t\tlet webhook = await this.client.webhooks.create(\n\t\t\targs.targetID,\n\t\t\targs.targetType,\n\t\t\tflags.address,\n\t\t\ttriggers\n\t\t);\n\t\tawait this.output(webhook);\n\t}\n}\n\nWebhooksCreateCommand.description = 'Create a new webhook';\nWebhooksCreateCommand.examples = [\n\t'box webhooks:create folder 22222 --triggers FILE.DELETED --address https://example.com/webhook/deletion',\n];\nWebhooksCreateCommand._endpoint = 'post_webhooks';\n\nWebhooksCreateCommand.flags = {\n\t...BoxCommand.flags,\n\t'id-only': Flags.boolean({\n\t\tdescription: 'Return only an ID to output from this command',\n\t}),\n\ttriggers: Flags.string({\n\t\tchar: 'T',\n\t\trequired: true,\n\t\tdescription:\n\t\t\t'Triggers for webhook as a comma separated list, e.g. FILE.DELETED,FILE.PREVIEWED',\n\t}),\n\taddress: Flags.string({\n\t\tchar: 'a',\n\t\trequired: true,\n\t\tdescription: 'URL for your webhook handler',\n\t}),\n};\n\nWebhooksCreateCommand.args = {\n\ttargetType: Args.string({\n\t\tname: 'targetType',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'Type of Box item to create a webhook on',\n\t\toptions: ['file', 'folder'],\n\t}),\n\ttargetID: Args.string({\n\t\tname: 'targetID',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the Box item to create a webhook on',\n\t}),\n};\n\nmodule.exports = WebhooksCreateCommand;\n"
  },
  {
    "path": "src/commands/webhooks/delete.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass WebhooksDeleteCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(WebhooksDeleteCommand);\n\n\t\tawait this.client.webhooks.delete(args.id);\n\t\tthis.info(`Deleted webhook ${args.id}`);\n\t}\n}\n\nWebhooksDeleteCommand.description = 'Delete a webhook';\nWebhooksDeleteCommand.examples = ['box webhooks:delete 12345'];\nWebhooksDeleteCommand._endpoint = 'delete_webhooks_id';\n\nWebhooksDeleteCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nWebhooksDeleteCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the webhook to delete',\n\t}),\n};\n\nmodule.exports = WebhooksDeleteCommand;\n"
  },
  {
    "path": "src/commands/webhooks/get.js",
    "content": "'use strict';\n\nconst { Args } = require('@oclif/core');\nconst BoxCommand = require('../../box-command');\n\nclass WebhooksGetCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { args } = await this.parse(WebhooksGetCommand);\n\n\t\tlet webhook = await this.client.webhooks.get(args.id);\n\t\tawait this.output(webhook);\n\t}\n}\n\nWebhooksGetCommand.description = 'Get information about a webhook';\nWebhooksGetCommand.examples = ['box webhooks:get 12345'];\nWebhooksGetCommand._endpoint = 'get_webhooks_id';\n\nWebhooksGetCommand.flags = {\n\t...BoxCommand.flags,\n};\n\nWebhooksGetCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the webhook to get',\n\t}),\n};\n\nmodule.exports = WebhooksGetCommand;\n"
  },
  {
    "path": "src/commands/webhooks/index.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst PaginationUtilities = require('../../pagination-utils');\n\nclass WebhooksListCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags } = await this.parse(WebhooksListCommand);\n\t\tlet options = PaginationUtilities.handlePagination(flags);\n\n\t\tlet webhooks = await this.client.webhooks.getAll(options);\n\t\tawait this.output(webhooks);\n\t}\n}\n\nWebhooksListCommand.aliases = ['webhooks:list'];\n\nWebhooksListCommand.description = 'List all webhooks';\nWebhooksListCommand.examples = ['box webhooks'];\nWebhooksListCommand._endpoint = 'get_webhooks';\n\nWebhooksListCommand.flags = {\n\t...BoxCommand.flags,\n\t...PaginationUtilities.flags,\n};\n\nmodule.exports = WebhooksListCommand;\n"
  },
  {
    "path": "src/commands/webhooks/update.js",
    "content": "'use strict';\n\nconst BoxCommand = require('../../box-command');\nconst { Flags, Args } = require('@oclif/core');\n\nclass WebhooksUpdateCommand extends BoxCommand {\n\tasync run() {\n\t\tconst { flags, args } = await this.parse(WebhooksUpdateCommand);\n\t\tlet updates = {};\n\n\t\tif (flags.triggers) {\n\t\t\tupdates.triggers = flags.triggers.split(',');\n\t\t}\n\t\tif (flags.address) {\n\t\t\tupdates.address = flags.address;\n\t\t}\n\n\t\tlet webhook = await this.client.webhooks.update(args.id, updates);\n\t\tawait this.output(webhook);\n\t}\n}\n\nWebhooksUpdateCommand.description = 'Update a webhook';\nWebhooksUpdateCommand.examples = [\n\t'box webhooks:update 12345 --triggers FILE.DELETED,FOLDER.DELETED',\n];\nWebhooksUpdateCommand._endpoint = 'put_webhooks_id';\n\nWebhooksUpdateCommand.flags = {\n\t...BoxCommand.flags,\n\ttriggers: Flags.string({\n\t\tchar: 'T',\n\t\tdescription:\n\t\t\t'Triggers for webhook, enter as comma separated list. For example: FILE.DELETED,FILE.PREVIEWED',\n\t}),\n\taddress: Flags.string({\n\t\tchar: 'a',\n\t\tdescription: 'URL for your webhook handler',\n\t}),\n};\n\nWebhooksUpdateCommand.args = {\n\tid: Args.string({\n\t\tname: 'id',\n\t\trequired: true,\n\t\thidden: false,\n\t\tdescription: 'ID of the webhook to update',\n\t}),\n};\n\nmodule.exports = WebhooksUpdateCommand;\n"
  },
  {
    "path": "src/debug.js",
    "content": "'use strict';\n\nconst debug = require('debug');\n\nmodule.exports = Object.freeze({\n\tinit: debug('box-cli:init'),\n\texecute: debug('box-cli:execute'),\n\toutput: debug('box-cli:output'),\n});\n"
  },
  {
    "path": "src/github-updater.js",
    "content": "'use strict';\n\nconst { ux } = require('@oclif/core');\nconst makeDebug = require('debug');\nconst { Updater } = require('@oclif/plugin-update/lib/update');\n\nconst debug = makeDebug('oclif:update:github');\n\nlet octokitInstance = null;\n\nasync function getOctokit() {\n\tif (!octokitInstance) {\n\t\tconst { Octokit } = await import('@octokit/rest');\n\t\toctokitInstance = new Octokit({\n\t\t\tauth: process.env.GITHUB_TOKEN || process.env.GH_TOKEN,\n\t\t});\n\t}\n\treturn octokitInstance;\n}\n\nfunction checkGitHubConfig(config) {\n\tconst githubConfig = config.pjson.oclif.update?.github;\n\n\tif (\n\t\tgithubConfig &&\n\t\ttypeof githubConfig === 'object' &&\n\t\t'owner' in githubConfig &&\n\t\t'repo' in githubConfig\n\t) {\n\t\treturn {\n\t\t\towner: githubConfig.owner,\n\t\t\trepo: githubConfig.repo,\n\t\t};\n\t}\n\n\t// Try to parse from repository field\n\tconst repo = config.pjson.repository;\n\tif (typeof repo === 'string') {\n\t\t// Handle formats like \"owner/repo\" or \"github:owner/repo\" or \"https://github.com/owner/repo\"\n\t\tconst match =\n\t\t\trepo.match(/^(?:github:)?([^/]+)\\/([^/]+?)(?:\\.git)?$/u) ||\n\t\t\trepo.match(/github\\.com\\/([^/]+)\\/([^/]+?)(?:\\.git)?$/u);\n\n\t\tif (match) {\n\t\t\treturn {\n\t\t\t\towner: match[1],\n\t\t\t\trepo: match[2],\n\t\t\t};\n\t\t}\n\t}\n\n\treturn null;\n}\n\nclass GitHubUpdater extends Updater {\n\tconstructor(config) {\n\t\tsuper(config);\n\t\tthis.githubConfig = this.getGitHubConfig();\n\t\tthis.octokit = null;\n\t}\n\n\tasync ensureOctokit() {\n\t\tif (!this.octokit) {\n\t\t\tthis.octokit = await getOctokit();\n\t\t}\n\t}\n\n\t// Override runUpdate to use GitHub-specific methods\n\t// Since the base class has private methods for fetching manifests,\n\t// we need to override the entire runUpdate to use GitHub APIs\n\tasync runUpdate(options) {\n\t\tconst { autoUpdate, version, force = false } = options;\n\n\t\tif (autoUpdate) {\n\t\t\tawait this.debounce();\n\t\t}\n\n\t\tux.action.start(`${this.config.name}: Updating CLI`);\n\n\t\tif (this.notUpdatable()) {\n\t\t\tux.action.stop('not updatable');\n\t\t\treturn;\n\t\t}\n\n\t\tconst channel = 'stable';\n\t\tconst current = await this.determineCurrentVersion();\n\n\t\tif (version) {\n\t\t\tconst localVersion = force\n\t\t\t\t? null\n\t\t\t\t: await this.findLocalVersion(version);\n\n\t\t\tif (this.alreadyOnVersion(current, localVersion || null)) {\n\t\t\t\tux.action.stop(\n\t\t\t\t\tthis.config.scopedEnvVar('HIDE_UPDATED_MESSAGE')\n\t\t\t\t\t\t? 'done'\n\t\t\t\t\t\t: `already on version ${current}`\n\t\t\t\t);\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tawait this.config.runHook('preupdate', { channel, version });\n\n\t\t\tif (localVersion) {\n\t\t\t\tawait this.updateToExistingVersion(current, localVersion);\n\t\t\t} else {\n\t\t\t\tconst index = await this.fetchVersionIndex();\n\t\t\t\tconst url = index[version];\n\t\t\t\tif (!url) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`${version} not found in index:\\n${Object.keys(index).join(', ')}`\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tconst manifest = await this.fetchGitHubManifest(version, url);\n\t\t\t\tconst updated = manifest.sha\n\t\t\t\t\t? `${manifest.version}-${manifest.sha}`\n\t\t\t\t\t: manifest.version;\n\t\t\t\tawait this.update(manifest, current, updated, force, channel);\n\t\t\t}\n\n\t\t\tawait this.config.runHook('update', { channel, version });\n\t\t\tux.action.stop();\n\t\t\tux.stdout();\n\t\t\tux.stdout(\n\t\t\t\t`Updating to a specific version will not update the channel. If autoupdate is enabled, the CLI will eventually be updated back to ${channel}.`\n\t\t\t);\n\t\t} else {\n\t\t\tconst manifest = await this.fetchGitHubManifest();\n\t\t\tconst updated = manifest.sha\n\t\t\t\t? `${manifest.version}-${manifest.sha}`\n\t\t\t\t: manifest.version;\n\n\t\t\tif (!force && this.alreadyOnVersion(current, updated)) {\n\t\t\t\tux.action.stop(\n\t\t\t\t\tthis.config.scopedEnvVar('HIDE_UPDATED_MESSAGE')\n\t\t\t\t\t\t? 'done'\n\t\t\t\t\t\t: `already on version ${current}`\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tawait this.config.runHook('preupdate', {\n\t\t\t\t\tchannel,\n\t\t\t\t\tversion: updated,\n\t\t\t\t});\n\t\t\t\tawait this.update(manifest, current, updated, force, channel);\n\t\t\t}\n\n\t\t\tawait this.config.runHook('update', { channel, version: updated });\n\t\t\tux.action.stop();\n\t\t}\n\n\t\tawait this.touch();\n\t\tawait this.tidy();\n\t}\n\n\t// Override fetchVersionIndex to use GitHub releases\n\tasync fetchVersionIndex() {\n\t\treturn this.fetchGitHubVersionIndex();\n\t}\n\n\t// GitHub-specific implementation\n\tasync fetchGitHubVersionIndex() {\n\t\tawait this.ensureOctokit();\n\t\tux.action.status = 'fetching version index from GitHub';\n\n\t\tconst { owner, repo } = this.githubConfig;\n\n\t\ttry {\n\t\t\tdebug(`Fetching releases for ${owner}/${repo}`);\n\t\t\tconst { data: releases } = await this.octokit.repos.listReleases({\n\t\t\t\towner,\n\t\t\t\tper_page: 100,\n\t\t\t\trepo,\n\t\t\t});\n\n\t\t\tconst versionIndex = {};\n\n\t\t\tfor (const release of releases) {\n\t\t\t\t// Extract version from tag_name (remove 'v' prefix if present)\n\t\t\t\tconst version = release.tag_name.replace(/^v/u, '');\n\n\t\t\t\t// Find the appropriate asset for this platform/arch\n\t\t\t\tconst assetName = this.determineAssetName(version);\n\t\t\t\tconst asset = release.assets.find((a) => a.name === assetName);\n\n\t\t\t\tif (asset) {\n\t\t\t\t\tversionIndex[version] = asset.browser_download_url;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tdebug(`Found ${Object.keys(versionIndex).length} versions`);\n\t\t\treturn versionIndex;\n\t\t} catch (error) {\n\t\t\tdebug('Failed to fetch GitHub releases', error);\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to fetch releases from GitHub repository ${owner}/${repo}`\n\t\t\t);\n\t\t}\n\t}\n\n\t// GitHub-specific manifest fetching\n\t// Fetches latest release if no version specified, or specific version if provided\n\tasync fetchGitHubManifest(version = null, fallbackUrl = null) {\n\t\tawait this.ensureOctokit();\n\t\tux.action.status = 'fetching manifest from GitHub';\n\n\t\tconst { owner, repo } = this.githubConfig;\n\n\t\ttry {\n\t\t\tlet release;\n\n\t\t\tif (version) {\n\t\t\t\tdebug(`Fetching release v${version} for ${owner}/${repo}`);\n\t\t\t\tconst { data } = await this.octokit.repos.getReleaseByTag({\n\t\t\t\t\towner,\n\t\t\t\t\trepo,\n\t\t\t\t\ttag: `v${version}`,\n\t\t\t\t});\n\t\t\t\trelease = data;\n\t\t\t} else {\n\t\t\t\tdebug(`Fetching latest release for ${owner}/${repo}`);\n\t\t\t\tconst { data } = await this.octokit.repos.getLatestRelease({\n\t\t\t\t\towner,\n\t\t\t\t\trepo,\n\t\t\t\t});\n\t\t\t\trelease = data;\n\t\t\t}\n\n\t\t\tconst releaseVersion = release.tag_name.replace(/^v/u, '');\n\t\t\tconst assetName = this.determineAssetName(releaseVersion);\n\t\t\tconst asset = release.assets.find((a) => a.name === assetName);\n\n\t\t\tif (!asset) {\n\t\t\t\t// If we have a fallback URL (for specific version), use it\n\t\t\t\tif (fallbackUrl) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tgz: fallbackUrl,\n\t\t\t\t\t\tversion: version || releaseVersion,\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// Otherwise, throw an error\n\t\t\t\tconst config = this.config;\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No suitable asset found for ${config.platform}-${config.arch} in release ${release.tag_name}`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Return manifest with the asset URL and SHA256 digest\n\t\t\tconst manifest = {\n\t\t\t\tgz: asset.browser_download_url,\n\t\t\t\tversion: releaseVersion,\n\t\t\t};\n\n\t\t\t// Add SHA256 digest if available (format: \"sha256:hash\")\n\t\t\tif (asset.digest) {\n\t\t\t\tconst sha256Match = asset.digest.match(/^sha256:(.+)$/);\n\t\t\t\tif (sha256Match) {\n\t\t\t\t\tmanifest.sha256gz = sha256Match[1];\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn manifest;\n\t\t} catch (error) {\n\t\t\t// If we have a fallback URL, use it\n\t\t\tif (fallbackUrl && version) {\n\t\t\t\tdebug(\n\t\t\t\t\t'Failed to fetch version manifest, using fallback URL',\n\t\t\t\t\terror\n\t\t\t\t);\n\t\t\t\treturn {\n\t\t\t\t\tgz: fallbackUrl,\n\t\t\t\t\tversion,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst statusCode = error.status;\n\t\t\tif (statusCode === 404) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\tversion\n\t\t\t\t\t\t? `Release v${version} not found in ${owner}/${repo}`\n\t\t\t\t\t\t: `Release not found in ${owner}/${repo}`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tthrow error;\n\t\t}\n\t}\n\n\tdetermineAssetName(version) {\n\t\tconst config = this.config;\n\t\tconst platform = config.platform === 'wsl' ? 'linux' : config.platform;\n\t\tconst ext = config.windows ? 'tar.gz' : 'tar.gz';\n\t\treturn `${config.bin}-v${version}-${platform}-${config.arch}.${ext}`;\n\t}\n\n\tgetGitHubConfig() {\n\t\tconst oclifConfig = this.config;\n\t\tconst config = checkGitHubConfig(oclifConfig);\n\t\tif (!config) {\n\t\t\tthrow new Error(\n\t\t\t\t'GitHub repository not configured. Add \"oclif.update.github\" with \"owner\" and \"repo\" fields to package.json'\n\t\t\t);\n\t\t}\n\n\t\treturn config;\n\t}\n}\n\nmodule.exports = GitHubUpdater;\n"
  },
  {
    "path": "src/hooks/init/verbose.js",
    "content": "'use strict';\n\nconst debug = require('debug');\n\nmodule.exports = function verbose(options) {\n\tif (\n\t\tArray.isArray(options.argv) &&\n\t\toptions.argv.some((f) => f === '-v' || f === '--verbose')\n\t) {\n\t\tdebug.enable('box*');\n\t}\n};\n"
  },
  {
    "path": "src/index.js",
    "content": "'use strict';\n\nmodule.exports = require('@oclif/core');\n"
  },
  {
    "path": "src/inquirer.js",
    "content": "'use strict';\n\n// restore-cursor@3 (used by inquirer@8) calls require('signal-exit') as a\n// function, but signal-exit@4 exports an object with an onExit() method.\n//\n// Locally, npm nests signal-exit@3 under restore-cursor, so both versions\n// coexist. In the standalone Windows build produced by oclif pack:win, module\n// resolution ends up pointing restore-cursor to top-level signal-exit@4\n// (effectively like a flattened/deduped node_modules layout), which causes\n// \"signalExit is not a function\" on Windows.\n//\n// Node's lookup order for require('signal-exit') from restore-cursor is:\n// 1) restore-cursor/node_modules/signal-exit\n// 2) parent node_modules/signal-exit\n// If step (1) is absent in the packaged layout, step (2) resolves to v4.\n//\n// This started surfacing after dependency-tree changes included in v4.5.0\n// (notably commit 4f4254d), where top-level signal-exit moved to 4.1.0.\n//\n// This shim wraps the v4 object export as a callable function before inquirer\n// (and its restore-cursor dependency) is loaded.\n\nconst SIGNAL_EXIT_ID = 'signal-exit';\nconst signalExit = require(SIGNAL_EXIT_ID);\n\nif (\n\ttypeof signalExit !== 'function' &&\n\ttypeof signalExit.onExit === 'function'\n) {\n\tconst compatSignalExit = (...args) => signalExit.onExit(...args);\n\tObject.assign(compatSignalExit, signalExit);\n\n\tconst resolvedPath = require.resolve(SIGNAL_EXIT_ID);\n\tif (require.cache[resolvedPath]) {\n\t\trequire.cache[resolvedPath].exports = compatSignalExit;\n\t}\n}\n\nmodule.exports = require('inquirer');\n"
  },
  {
    "path": "src/logged-in.html",
    "content": "<!DOCTYPE html>\n<html>\n\n<head>\n    <style>\n        html {\n            margin: 0;\n            height: 100%;\n        }\n\n        body {\n            display: flex;\n            flex-direction: column;\n            justify-content: center;\n            align-items: center;\n            margin: 0;\n            height: 100%;\n        }\n\n        .dot {\n            height: 7px;\n            width: 7px;\n            background-color: #bbb;\n            border-radius: 50%;\n            margin-left: 5px;\n            position: relative;\n            z-index: 1;\n        }\n\n        .dot-close {\n            background-color: #FE554F;\n        }\n\n        .dot-minimize {\n            background-color: #FEB728;\n        }\n\n        .dot-expand {\n            background-color: #29BD36;\n        }\n\n        .title-bar {\n            display: flex;\n            height: 15px;\n            width: 50%;\n            min-width: 500px;\n            max-width: 600px;\n            /* background-color: #233659; */\n            position: relative;\n            justify-content: space-between;\n            background-color: #000000;\n            border-radius: 10px 10px 0 0;\n            align-items: center;\n        }\n\n        .terminal {\n            border-radius: 0 0 10px 10px;\n            height: 33%;\n            width: 50%;\n            min-width: 500px;\n            max-width: 600px;\n            background-color: black;\n            -webkit-box-shadow: 0px -17px 30px 2px #ADADAD, 0px 0px 30px 2px #ADADAD;\n            -moz-box-shadow: 0px -17px 30px 2px #ADADAD, 0px 0px 30px 2px #ADADAD;\n            box-shadow: 0px -17px 30px 2px #ADADAD, 0px 0px 30px 2px #ADADAD;\n        }\n\n        .message {\n            color: white;\n            z-index: 10;\n            padding: 10px;\n            font-family: SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace;\n            font-size: 15px;\n        }\n\n        .green {\n            color: #4AF626;\n        }\n\n        .css-typing p {\n            border-right: .15em solid #4AF626;\n            font-family: \"Courier\";\n            font-size: 14px;\n            white-space: nowrap;\n            overflow: hidden;\n            color: white;\n            margin: 10px;\n        }\n\n        .css-typing p:nth-child(1) {\n            width: 30em;\n            opacity: 0;\n            -webkit-animation: type 2s steps(60, end), blink .5s step-end alternate;\n            animation: type 2s steps(60, end), blink .5s step-end alternate;\n            -webkit-animation-fill-mode: forwards;\n            animation-fill-mode: forwards;\n        }\n\n        .css-typing p:nth-child(2) {\n            width: 29.5em;\n            opacity: 0;\n            -webkit-animation: type2 2s steps(60, end), blink .5s step-end infinite alternate;\n            animation: type2 2s steps(60, end), blink .5s step-end infinite alternate;\n            -webkit-animation-delay: 2s;\n            animation-delay: 2s;\n            -webkit-animation-fill-mode: forwards;\n            animation-fill-mode: forwards;\n        }\n\n\n        @keyframes type {\n            0% {\n                width: 0;\n            }\n\n            1% {\n                opacity: 1;\n            }\n\n            99.9% {\n                border-right: .15em solid #4AF626;\n            }\n\n            100% {\n                opacity: 1;\n                border: none;\n            }\n        }\n\n        @-webkit-keyframes type {\n            0% {\n                width: 0;\n            }\n\n            1% {\n                opacity: 1;\n            }\n\n            99.9% {\n                border-right: .15em solid #4AF626;\n            }\n\n            100% {\n                opacity: 1;\n                border: none;\n            }\n        }\n\n        @keyframes type2 {\n            0% {\n                width: 0;\n            }\n\n            1% {\n                opacity: 1;\n            }\n\n            100% {\n                opacity: 1;\n            }\n        }\n\n        @-webkit-keyframes type2 {\n            0% {\n                width: 0;\n            }\n\n            1% {\n                opacity: 1;\n            }\n\n            100% {\n                opacity: 1;\n            }\n        }\n\n        @keyframes blink {\n            50% {\n                border-color: transparent;\n            }\n        }\n\n        @-webkit-keyframes blink {\n            50% {\n                border-color: transparent;\n            }\n        }\n    </style>\n</head>\n\n<body>\n    <div class=\"title-bar\">\n        <div style=\"display: flex;\">\n            <div class=\"dot dot-close\"></div>\n            <div class=\"dot dot-minimize\"></div>\n            <div class=\"dot dot-expand\"></div>\n        </div>\n    </div>\n    <div class=\"terminal\">\n        <div class=\"css-typing\">\n            <p id=\"username\">\n                <span class=\"green\">$</span> You are logged in as <span class=\"green\">example@box.com</span>!\n            </p>\n            <p>\n                <span class=\"green\">$</span> You can close this page and return to your CLI.\n            </p>\n        </div>\n    </div>\n</body>\n</html>"
  },
  {
    "path": "src/login-helper.js",
    "content": "'use strict';\n\nconst BoxCLIError = require('./cli-error');\n\nfunction assertValidOAuthCode(code) {\n\tif (typeof code !== 'string' || code.length === 0) {\n\t\tthrow new BoxCLIError(\n\t\t\t`Invalid OAuth code received in callback. Got \"${code}\"`\n\t\t);\n\t}\n}\n\nasync function getTokenInfoByAuthCode(sdk, code, redirectUri, codeVerifier) {\n\tif (!sdk?.tokenManager?.getTokens) {\n\t\tthrow new BoxCLIError(\n\t\t\t'OAuth token manager is unavailable; unable to complete token exchange.'\n\t\t);\n\t}\n\n\ttry {\n\t\tconst grantPayload = {\n\t\t\tgrant_type: 'authorization_code',\n\t\t\tcode,\n\t\t\tredirect_uri: redirectUri,\n\t\t};\n\t\tif (codeVerifier) {\n\t\t\tgrantPayload.code_verifier = codeVerifier;\n\t\t}\n\n\t\treturn await sdk.tokenManager.getTokens(grantPayload, null);\n\t} catch (error) {\n\t\tthrow new BoxCLIError(\n\t\t\t'Failed to exchange auth code for tokens.',\n\t\t\terror\n\t\t);\n\t}\n}\n\nmodule.exports = {\n\tassertValidOAuthCode,\n\tgetTokenInfoByAuthCode,\n};\n"
  },
  {
    "path": "src/modules/collaboration.js",
    "content": "'use strict';\n\n/**\n * Module for shared code around collaboration endpoints\n */\nclass CollaborationModule {\n\t/**\n\t * @param {BoxClient} client The client to use for API requests\n\t * @constructor\n\t */\n\tconstructor(client) {\n\t\tthis.client = client;\n\t}\n\n\t/**\n\t * Create a collaboration on an item for a user\n\t *\n\t * @param {Object} args The parsed oclif command-line arguments\n\t * @param {Object} flags The parsed oclif command-line flags\n\t * @returns {Promise<Object>} A promise resolving to the created collaboration object\n\t */\n\tcreateCollaboration(arguments_, flags) {\n\t\tlet parameters = {\n\t\t\tbody: {\n\t\t\t\titem: {\n\t\t\t\t\ttype: arguments_.itemType,\n\t\t\t\t\tid: arguments_.itemID,\n\t\t\t\t},\n\t\t\t\taccessible_by: {},\n\t\t\t},\n\t\t\tqs: {},\n\t\t};\n\n\t\tif (flags.fields) {\n\t\t\tparameters.qs.fields = flags.fields;\n\t\t}\n\t\tif (Object.hasOwn(flags, 'notify')) {\n\t\t\tparameters.qs.notify = flags.notify;\n\t\t}\n\t\tif (Object.hasOwn(flags, 'can-view-path')) {\n\t\t\tparameters.body.can_view_path = flags['can-view-path'];\n\t\t}\n\t\tif (flags.role) {\n\t\t\tparameters.body.role = flags.role.replace('_', ' ');\n\t\t} else if (flags.editor) {\n\t\t\tparameters.body.role = this.client.collaborationRoles.EDITOR;\n\t\t} else if (flags.viewer) {\n\t\t\tparameters.body.role = this.client.collaborationRoles.VIEWER;\n\t\t} else if (flags.previewer) {\n\t\t\tparameters.body.role = this.client.collaborationRoles.PREVIEWER;\n\t\t} else if (flags.uploader) {\n\t\t\tparameters.body.role = this.client.collaborationRoles.UPLOADER;\n\t\t} else if (flags['previewer-uploader']) {\n\t\t\tparameters.body.role =\n\t\t\t\tthis.client.collaborationRoles.PREVIEWER_UPLOADER;\n\t\t} else if (flags['viewer-uploader']) {\n\t\t\tparameters.body.role =\n\t\t\t\tthis.client.collaborationRoles.VIEWER_UPLOADER;\n\t\t} else if (flags['co-owner']) {\n\t\t\tparameters.body.role = this.client.collaborationRoles.CO_OWNER;\n\t\t}\n\t\tif (!parameters.body.role) {\n\t\t\tthrow new Error('Missing required flag for collaboration role');\n\t\t}\n\n\t\tif (flags['user-id']) {\n\t\t\tparameters.body.accessible_by.type = 'user';\n\t\t\tparameters.body.accessible_by.id = flags['user-id'];\n\t\t} else if (flags['group-id']) {\n\t\t\tparameters.body.accessible_by.type = 'group';\n\t\t\tparameters.body.accessible_by.id = flags['group-id'];\n\t\t} else if (flags.login) {\n\t\t\tparameters.body.accessible_by.type = 'user';\n\t\t\tparameters.body.accessible_by.login = flags.login;\n\t\t}\n\n\t\t// @TODO (2018-07-07): Should implement this using the Node SDK\n\t\treturn this.client.wrapWithDefaultHandler(this.client.post)(\n\t\t\t'/collaborations',\n\t\t\tparameters\n\t\t);\n\t}\n}\n\nmodule.exports = CollaborationModule;\n"
  },
  {
    "path": "src/modules/shared-links.js",
    "content": "'use strict';\n\nconst BoxCLIError = require('../cli-error');\n\n/**\n * Module for shared code around shared links functionality\n */\nclass SharedLinksModule {\n\t/**\n\t * @param {BoxClient} client The client to use for API requests\n\t * @constructor\n\t */\n\tconstructor(client) {\n\t\tthis.client = client;\n\t}\n\n\t/**\n\t * Create a shared link for an item\n\t *\n\t * @param {Object} args The parsed oclif command-line arguments\n\t * @param {Object} flags The parsed oclif command-line flags\n\t * @returns {Promise<Object>} A promise resolving to the updated item object\n\t */\n\tcreateSharedLink(arguments_, flags) {\n\t\tlet updates = {\n\t\t\tshared_link: { permissions: {} },\n\t\t\tfields: 'shared_link',\n\t\t};\n\n\t\tif (flags.access) {\n\t\t\tupdates.shared_link.access = flags.access;\n\t\t}\n\t\tif (flags.password) {\n\t\t\tupdates.shared_link.password = flags.password;\n\t\t}\n\t\tif (flags['unshared-at']) {\n\t\t\tupdates.shared_link.unshared_at = flags['unshared-at'];\n\t\t}\n\t\tif (Object.hasOwn(flags, 'can-download')) {\n\t\t\tupdates.shared_link.permissions.can_download =\n\t\t\t\tflags['can-download'];\n\t\t}\n\t\tif (flags['vanity-name']) {\n\t\t\tupdates.shared_link.vanity_name = flags['vanity-name'];\n\t\t}\n\n\t\tif (arguments_.itemType === 'file') {\n\t\t\tif (Object.hasOwn(flags, 'can-edit')) {\n\t\t\t\tupdates.shared_link.permissions.can_edit = flags['can-edit'];\n\t\t\t}\n\t\t\treturn this.client.files.update(arguments_.itemID, updates);\n\t\t} else if (arguments_.itemType === 'folder') {\n\t\t\treturn this.client.folders.update(arguments_.itemID, updates);\n\t\t}\n\t\tthrow new BoxCLIError(\n\t\t\t`Unsupported item type for shared link creation: ${arguments_.itemType}`\n\t\t);\n\t}\n\n\t/**\n\t * Remove a shared link from an item\n\t *\n\t * @param {Object} args The parsed oclif command-line arguments\n\t * @returns {Promise<Object>} A promise resolving to the updated item object\n\t */\n\tremoveSharedLink(arguments_) {\n\t\tlet updates = { shared_link: null };\n\n\t\tif (arguments_.itemType === 'file') {\n\t\t\treturn this.client.files.update(arguments_.itemID, updates);\n\t\t} else if (arguments_.itemType === 'folder') {\n\t\t\treturn this.client.folders.update(arguments_.itemID, updates);\n\t\t}\n\t\tthrow new BoxCLIError(\n\t\t\t`Unsupported item type for shared link removal: ${arguments_.itemType}`\n\t\t);\n\t}\n}\n\nmodule.exports = SharedLinksModule;\n"
  },
  {
    "path": "src/modules/upload.js",
    "content": "'use strict';\n\nconst fs = require('node:fs');\nconst progress = require('cli-progress');\nconst BoxCLIError = require('../cli-error');\n\nconst CHUNKED_UPLOAD_FILE_SIZE = 1024 * 1024 * 100; // 100 MiB\n\nfunction createReadStream(filePath) {\n\ttry {\n\t\treturn fs.createReadStream(filePath);\n\t} catch (error) {\n\t\tthrow new BoxCLIError(`Could not open file ${filePath}`, error);\n\t}\n}\n\nfunction runChunkedUpload(uploader, size) {\n\tconst progressBar = new progress.Bar({\n\t\tformat: '[{bar}] {percentage}% | ETA: {eta_formatted} | {value}/{total} | Speed: {speed} MB/s',\n\t\tstopOnComplete: true,\n\t});\n\tlet bytesUploaded = 0;\n\tconst startTime = Date.now();\n\tprogressBar.start(size, 0, { speed: 'N/A' });\n\tuploader.on('chunkUploaded', (chunk) => {\n\t\tbytesUploaded += chunk.part.size;\n\t\tprogressBar.update(bytesUploaded, {\n\t\t\tspeed: Math.floor(bytesUploaded / (Date.now() - startTime) / 1000),\n\t\t});\n\t});\n\treturn uploader.start();\n}\n\nasync function uploadFile(\n\tclient,\n\t{ folderID, name, stream, size, fileAttributes }\n) {\n\tif (size < CHUNKED_UPLOAD_FILE_SIZE) {\n\t\treturn client.files.uploadFile(folderID, name, stream, fileAttributes);\n\t}\n\tconst uploader = await client.files.getChunkedUploader(\n\t\tfolderID,\n\t\tsize,\n\t\tname,\n\t\tstream,\n\t\t{ fileAttributes }\n\t);\n\treturn runChunkedUpload(uploader, size);\n}\n\nasync function uploadNewFileVersion(\n\tclient,\n\t{ fileID, stream, size, fileAttributes }\n) {\n\tif (size < CHUNKED_UPLOAD_FILE_SIZE) {\n\t\treturn client.files.uploadNewFileVersion(\n\t\t\tfileID,\n\t\t\tstream,\n\t\t\tfileAttributes\n\t\t);\n\t}\n\tconst uploader = await client.files.getNewVersionChunkedUploader(\n\t\tfileID,\n\t\tsize,\n\t\tstream,\n\t\t{ fileAttributes }\n\t);\n\treturn runChunkedUpload(uploader, size);\n}\n\nmodule.exports = {\n\tCHUNKED_UPLOAD_FILE_SIZE,\n\tcreateReadStream,\n\tuploadFile,\n\tuploadNewFileVersion,\n};\n"
  },
  {
    "path": "src/modules/user.js",
    "content": "'use strict';\n\n/**\n * Module for shared code around user endpoints\n */\nclass UserModule {\n\t/**\n\t * @param {BoxClient} client The client to use for API requests\n\t * @constructor\n\t */\n\tconstructor(client) {\n\t\tthis.client = client;\n\t}\n\n\t/**\n\t * List the users in an enterprise using optional filters\n\t *\n\t * @param {Object} flags The parsed oclif command-line flags\n\t * @returns {Promise<Object>} A promise resolving to the collection of user objects\n\t */\n\tlistUsers(flags) {\n\t\tlet options = {};\n\n\t\tif (flags.fields) {\n\t\t\toptions.fields = flags.fields;\n\t\t}\n\n\t\tif (flags['all-users']) {\n\t\t\toptions.user_type = 'all';\n\t\t} else if (flags['managed-users']) {\n\t\t\toptions.user_type = 'managed';\n\t\t} else if (flags['app-users']) {\n\t\t\toptions.filter_term = 'AppUser_';\n\t\t} else if (flags['external-users']) {\n\t\t\toptions.user_type = 'external';\n\t\t}\n\n\t\tif (flags.limit) {\n\t\t\toptions.limit = flags.limit;\n\t\t}\n\n\t\t// forcing offset based pagination for now. Using filter_term causes infinite loop because next_marker is never null\n\t\t// if (flags.usemarker) {\n\t\t// \toptions.usemarker = flags.usemarker;\n\t\t// }\n\n\t\tif (flags.filter) {\n\t\t\toptions.filter_term = flags.filter;\n\t\t}\n\n\t\treturn this.client.enterprise.getUsers(options);\n\t}\n}\n\nmodule.exports = UserModule;\n"
  },
  {
    "path": "src/pagination-utils.js",
    "content": "'use strict';\n\nconst { Flags } = require('@oclif/core');\n\nconst MAX_LIMIT = 1000;\n\n/**\n * Sets correct limit option based on max-items flag.\n * If max-items is not present limit is set to 1000\n *\n * @param {Object} commandFlags Flags from the command\n * @returns {Object} Options for http request\n * @private\n *\n **/\nfunction parsePaginationFlags(commandFlags) {\n\tlet limitFlag =\n\t\tcommandFlags['max-items'] === undefined\n\t\t\t? MAX_LIMIT\n\t\t\t: commandFlags['max-items'];\n\n\tif (limitFlag <= 0) {\n\t\tthrow new Error('Max items must be greater than 0');\n\t}\n\n\tlet options = { limit: Math.min(MAX_LIMIT, limitFlag) };\n\n\treturn options;\n}\n\nmodule.exports = {\n\tforceMarkerPagination(commandFlags) {\n\t\tlet options = parsePaginationFlags(commandFlags);\n\t\toptions.usemarker = true;\n\n\t\treturn options;\n\t},\n\n\thandlePagination(commandFlags) {\n\t\treturn parsePaginationFlags(commandFlags);\n\t},\n};\n\nmodule.exports.flags = Object.freeze({\n\t'max-items': Flags.integer({\n\t\tdescription:\n\t\t\t'A value that indicates the maximum number of results to return. This only specifies a maximum boundary and will not guarantee the minimum number of results returned. When the max-items (x) is greater than 1000, then the maximum ceil(x/1000) requests will be made.',\n\t}),\n});\n"
  },
  {
    "path": "src/pkce-support.js",
    "content": "'use strict';\n\nconst { createHash, randomBytes } = require('node:crypto');\n\nconst MIN_PKCE_CODE_VERIFIER_LENGTH = 43;\nconst MAX_PKCE_CODE_VERIFIER_LENGTH = 128;\n\nfunction toBase64Url(buffer) {\n\treturn buffer\n\t\t.toString('base64')\n\t\t.replaceAll('+', '-')\n\t\t.replaceAll('/', '_')\n\t\t.replace(/=+$/u, '');\n}\n\nfunction generatePKCE(verifierLength = MAX_PKCE_CODE_VERIFIER_LENGTH) {\n\tif (\n\t\t!Number.isInteger(verifierLength) ||\n\t\tverifierLength < MIN_PKCE_CODE_VERIFIER_LENGTH ||\n\t\tverifierLength > MAX_PKCE_CODE_VERIFIER_LENGTH\n\t) {\n\t\tthrow new RangeError(\n\t\t\t`PKCE code verifier length must be an integer in range ${MIN_PKCE_CODE_VERIFIER_LENGTH}-${MAX_PKCE_CODE_VERIFIER_LENGTH}.`\n\t\t);\n\t}\n\n\t// Generate enough entropy and trim to requested PKCE verifier length.\n\tconst codeVerifier = toBase64Url(randomBytes(verifierLength)).slice(\n\t\t0,\n\t\tverifierLength\n\t);\n\tconst codeChallenge = toBase64Url(\n\t\tcreateHash('sha256').update(codeVerifier).digest()\n\t);\n\n\treturn { codeVerifier, codeChallenge };\n}\n\nmodule.exports = {\n\tMIN_PKCE_CODE_VERIFIER_LENGTH,\n\tMAX_PKCE_CODE_VERIFIER_LENGTH,\n\ttoBase64Url,\n\tgeneratePKCE,\n};\n"
  },
  {
    "path": "src/secure-storage.js",
    "content": "'use strict';\n\nconst { promisify } = require('node:util');\nconst DEBUG = require('./debug');\nconst PLATFORM_DARWIN = 'darwin';\nconst KEYTAR = 'keytar';\nconst KEYCHAIN = 'keychain';\n\n/**\n * Load an optional dependency and capture load errors.\n *\n * @param {string} packageName Package to load\n * @param {boolean} shouldLoad Whether this package should be loaded\n * @returns {{ loadedModule: unknown, loadError: unknown }} Result of loading\n */\nfunction loadOptionalModule(packageName, shouldLoad = true) {\n\tif (!shouldLoad) {\n\t\treturn { loadedModule: null, loadError: null };\n\t}\n\ttry {\n\t\treturn { loadedModule: require(packageName), loadError: null };\n\t} catch (error) {\n\t\treturn { loadedModule: null, loadError: error };\n\t}\n}\n\nconst { loadedModule: keytarModule, loadError: keytarLoadError } =\n\tloadOptionalModule(KEYTAR, process.platform !== PLATFORM_DARWIN);\nconst { loadedModule: keychainModule, loadError: keychainLoadError } =\n\tloadOptionalModule(KEYCHAIN, process.platform === PLATFORM_DARWIN);\n\nconst isDarwin = process.platform === PLATFORM_DARWIN;\nconst SUPPORTED_SECURE_STORAGE_PLATFORMS = [PLATFORM_DARWIN, 'win32', 'linux'];\nconst isSecurePlatform = SUPPORTED_SECURE_STORAGE_PLATFORMS.includes(\n\tprocess.platform\n);\n\n/**\n * Returns true when error indicates missing keychain/keytar entry.\n *\n * @param {unknown} error The caught error\n * @returns {boolean} Whether this is a \"secret not found\" error\n */\nfunction isSecretNotFoundError(error) {\n\tconst message = String(error?.message || '').toLowerCase();\n\treturn (\n\t\terror?.code === 'ENOENT' ||\n\t\tmessage.includes('not found') ||\n\t\tmessage.includes('password not found') ||\n\t\tmessage.includes('item not found') ||\n\t\tmessage.includes('could not find password')\n\t);\n}\n\n/**\n * Unified secure storage wrapper.\n *\n * On macOS uses the `keychain` npm module (which wraps `/usr/bin/security`).\n * ACL (Access Control List) in Keychain is a per-secret allowlist of apps\n * that can access the item without prompting. Using `keychain` avoids ACL\n * prompts because the accessing process is always the stable system\n * `security` binary, regardless of CLI binary identity/signature changes.\n * If we used `keytar` on macOS, access would come from the current\n * `node`/CLI executable identity; after signed-binary upgrades, macOS can\n * treat it as a different app and show ACL prompts for existing items.\n * That is why this module intentionally does not use `keytar` on macOS.\n *\n * On Windows/Linux uses `keytar` (native Keychain/Credential Vault/libsecret).\n */\nclass SecureStorage {\n\tconstructor() {\n\t\tif (isDarwin && keychainModule) {\n\t\t\tthis.backend = KEYCHAIN;\n\t\t\tthis.available = true;\n\t\t} else if (!isDarwin && isSecurePlatform && keytarModule) {\n\t\t\tthis.backend = KEYTAR;\n\t\t\tthis.available = true;\n\t\t} else {\n\t\t\tthis.backend = null;\n\t\t\tthis.available = false;\n\t\t}\n\n\t\tDEBUG.init('Secure storage initialized %O', {\n\t\t\tplatform: process.platform,\n\t\t\tarch: process.arch,\n\t\t\tbackend: this.backend,\n\t\t\tavailable: this.available,\n\t\t\tkeytarLoaded: Boolean(keytarModule),\n\t\t\tdarwinKeychainLoaded: Boolean(keychainModule),\n\t\t});\n\n\t\tif (!this.available) {\n\t\t\tif (isDarwin && !keychainModule) {\n\t\t\t\tDEBUG.init(\n\t\t\t\t\t'macOS keychain module not available: %s',\n\t\t\t\t\tkeychainLoadError?.message || 'unknown'\n\t\t\t\t);\n\t\t\t}\n\t\t\tif (!isDarwin && !keytarModule) {\n\t\t\t\tDEBUG.init(\n\t\t\t\t\t'keytar module not available: %s',\n\t\t\t\t\tkeytarLoadError?.message || 'unknown'\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t}\n\n\t/**\n\t * Read a password from secure storage.\n\t *\n\t * @param {string} service The service name\n\t * @param {string} account The account name\n\t * @returns {Promise<string|null>} The stored password, or null\n\t */\n\tasync getPassword(service, account) {\n\t\tif (!this.available) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (this.backend === KEYCHAIN) {\n\t\t\ttry {\n\t\t\t\tconst getPasswordAsync = promisify(\n\t\t\t\t\tkeychainModule.getPassword.bind(keychainModule)\n\t\t\t\t);\n\t\t\t\tconst password = await getPasswordAsync({\n\t\t\t\t\taccount,\n\t\t\t\t\tservice,\n\t\t\t\t});\n\t\t\t\treturn password || null;\n\t\t\t} catch (error) {\n\t\t\t\tif (isSecretNotFoundError(error)) {\n\t\t\t\t\treturn null;\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\treturn keytarModule.getPassword(service, account);\n\t}\n\n\t/**\n\t * Write a password to secure storage.\n\t *\n\t * @param {string} service The service name\n\t * @param {string} account The account name\n\t * @param {string} password The value to store\n\t * @returns {Promise<void>}\n\t */\n\tasync setPassword(service, account, password) {\n\t\tif (!this.available) {\n\t\t\tthrow new Error('Secure storage is not available');\n\t\t}\n\n\t\tif (this.backend === KEYCHAIN) {\n\t\t\tconst setPasswordAsync = promisify(\n\t\t\t\tkeychainModule.setPassword.bind(keychainModule)\n\t\t\t);\n\t\t\tawait setPasswordAsync({ account, service, password });\n\t\t\treturn;\n\t\t}\n\n\t\tawait keytarModule.setPassword(service, account, password);\n\t}\n\n\t/**\n\t * Delete a password from secure storage.\n\t *\n\t * @param {string} service The service name\n\t * @param {string} account The account name\n\t * @returns {Promise<boolean>} true if deleted\n\t */\n\tasync deletePassword(service, account) {\n\t\tif (!this.available) {\n\t\t\treturn false;\n\t\t}\n\n\t\tif (this.backend === KEYCHAIN) {\n\t\t\ttry {\n\t\t\t\tconst deletePasswordAsync = promisify(\n\t\t\t\t\tkeychainModule.deletePassword.bind(keychainModule)\n\t\t\t\t);\n\t\t\t\tawait deletePasswordAsync({ account, service });\n\t\t\t\treturn true;\n\t\t\t} catch (error) {\n\t\t\t\tif (isSecretNotFoundError(error)) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\treturn keytarModule.deletePassword(service, account);\n\t}\n}\n\nmodule.exports = new SecureStorage();\n"
  },
  {
    "path": "src/token-cache.js",
    "content": "'use strict';\n\n/* eslint-disable promise/catch-or-return,promise/no-callback-in-promise */\n\nconst fs = require('node:fs');\nconst os = require('node:os');\nconst path = require('node:path');\nconst BoxCLIError = require('./cli-error');\nconst utilities = require('./util');\nconst DEBUG = require('./debug');\nconst secureStorage = require('./secure-storage');\n\n/**\n * Cache interface used by the Node SDK to cache tokens to disk in the user's home directory\n * Supports secure storage with fallback to file system\n */\nclass CLITokenCache {\n\t/**\n\t * @constructor\n\t * @param {string} environmentName The name of the active CLI environment\n\t */\n\tconstructor(environmentName) {\n\t\tthis.environmentName = environmentName;\n\t\tthis.secureStorage = secureStorage;\n\t\tthis.filePath = path.join(\n\t\t\tos.homedir(),\n\t\t\t'.box',\n\t\t\t`${environmentName}_token_cache.json`\n\t\t);\n\t\tthis.serviceName = `boxcli-token-${environmentName}`;\n\t\tthis.accountName = 'Box';\n\t\tthis.supportsSecureStorage = this.secureStorage.available;\n\t}\n\n\t/**\n\t * Read tokens from secure storage with fallback to file system\n\t * @param {Function} callback The callback to pass resulting token info to\n\t * @returns {void}\n\t */\n\tread(callback) {\n\t\tif (this.supportsSecureStorage) {\n\t\t\tthis.secureStorage\n\t\t\t\t.getPassword(this.serviceName, this.accountName)\n\t\t\t\t.then((tokenJson) => {\n\t\t\t\t\tif (tokenJson) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tconst tokenInfo = JSON.parse(tokenJson);\n\t\t\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t\t\t'Loaded token from secure storage (%s) for environment: %s',\n\t\t\t\t\t\t\t\tthis.secureStorage.backend,\n\t\t\t\t\t\t\t\tthis.environmentName\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn callback(null, tokenInfo);\n\t\t\t\t\t\t} catch (parseError) {\n\t\t\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t\t\t'Failed to parse token from secure storage, falling back to file: %s',\n\t\t\t\t\t\t\t\tparseError.message\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t'No token found in secure storage for environment: %s; trying file cache',\n\t\t\t\t\t\tthis.environmentName\n\t\t\t\t\t);\n\t\t\t\t\treturn this._readFromFile(callback);\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t'Failed to read from secure storage (%s), falling back to file: %s',\n\t\t\t\t\t\tthis.secureStorage.backend,\n\t\t\t\t\t\terror?.message || error\n\t\t\t\t\t);\n\t\t\t\t\tthis._readFromFile(callback);\n\t\t\t\t});\n\t\t} else {\n\t\t\tDEBUG.init(\n\t\t\t\t'Secure storage unavailable for token cache; reading token from file for environment: %s',\n\t\t\t\tthis.environmentName\n\t\t\t);\n\t\t\tthis._readFromFile(callback);\n\t\t}\n\t}\n\n\t/**\n\t * Read tokens from file system\n\t * @param {Function} callback The callback to pass resulting token info to\n\t * @returns {void}\n\t * @private\n\t */\n\t_readFromFile(callback) {\n\t\tutilities\n\t\t\t.readFileAsync(this.filePath, 'utf8')\n\t\t\t.then((json) => {\n\t\t\t\tconst tokenInfo = JSON.parse(json);\n\t\t\t\tif (tokenInfo.accessToken) {\n\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t'Loaded token from file system for environment: %s (will be migrated to secure storage on next write)',\n\t\t\t\t\t\tthis.environmentName\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\treturn tokenInfo;\n\t\t\t})\n\t\t\t// If file is not present or not valid JSON, treat that as empty (but available) cache\n\t\t\t.catch(() => ({}))\n\t\t\t.then((tokenInfo) => callback(null, tokenInfo));\n\t}\n\n\t/**\n\t * Write tokens to secure storage with fallback to file system\n\t * @param {Object} tokenInfo The token object to write\n\t * @param {Function} callback The callback to pass results to\n\t * @returns {void}\n\t */\n\twrite(tokenInfo, callback) {\n\t\tconst output = JSON.stringify(tokenInfo, null, 4);\n\n\t\tif (this.supportsSecureStorage) {\n\t\t\tthis.secureStorage\n\t\t\t\t.setPassword(this.serviceName, this.accountName, output)\n\t\t\t\t.then(() => {\n\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t'Stored token in secure storage (%s) for environment: %s',\n\t\t\t\t\t\tthis.secureStorage.backend,\n\t\t\t\t\t\tthis.environmentName\n\t\t\t\t\t);\n\t\t\t\t\tif (fs.existsSync(this.filePath)) {\n\t\t\t\t\t\tfs.unlinkSync(this.filePath);\n\t\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t\t'Migrated token from file to secure storage for environment: %s',\n\t\t\t\t\t\t\tthis.environmentName\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn callback();\n\t\t\t\t})\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t'Failed to write to secure storage (%s) for environment %s, falling back to file: %s',\n\t\t\t\t\t\tthis.secureStorage.backend,\n\t\t\t\t\t\tthis.environmentName,\n\t\t\t\t\t\terror?.message || error\n\t\t\t\t\t);\n\t\t\t\t\tif (process.platform === 'linux') {\n\t\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t\t'To enable secure storage on Linux, install libsecret-1-dev package'\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tthis._writeToFile(output, callback);\n\t\t\t\t});\n\t\t} else {\n\t\t\tDEBUG.init(\n\t\t\t\t'Secure storage unavailable for token cache; writing token to file for environment: %s',\n\t\t\t\tthis.environmentName\n\t\t\t);\n\t\t\tthis._writeToFile(output, callback);\n\t\t}\n\t}\n\n\t/**\n\t * Write tokens to file system\n\t * @param {string} output The JSON string to write\n\t * @param {Function} callback The callback to pass results to\n\t * @returns {void}\n\t * @private\n\t */\n\t_writeToFile(output, callback) {\n\t\tutilities\n\t\t\t.writeFileAsync(this.filePath, output, 'utf8')\n\t\t\t// Pass success or error to the callback\n\t\t\t.then(callback)\n\t\t\t.catch((error) =>\n\t\t\t\tcallback(\n\t\t\t\t\tnew BoxCLIError('Failed to write to token cache', error)\n\t\t\t\t)\n\t\t\t);\n\t}\n\n\t/**\n\t * Delete the token from both secure storage and file system\n\t * @param {Function} callback The callback to pass results to\n\t * @returns {void}\n\t */\n\tclear(callback) {\n\t\tconst promises = [];\n\n\t\tif (this.supportsSecureStorage) {\n\t\t\tpromises.push(\n\t\t\t\tthis.secureStorage\n\t\t\t\t\t.deletePassword(this.serviceName, this.accountName)\n\t\t\t\t\t.then((deleted) => {\n\t\t\t\t\t\tif (!deleted) {\n\t\t\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t\t\t'No token found in secure storage for environment: %s',\n\t\t\t\t\t\t\t\tthis.environmentName\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn deleted;\n\t\t\t\t\t})\n\t\t\t\t\t.catch((error) => {\n\t\t\t\t\t\tconst message = String(\n\t\t\t\t\t\t\terror?.message || ''\n\t\t\t\t\t\t).toLowerCase();\n\t\t\t\t\t\tconst isMissingSecretError =\n\t\t\t\t\t\t\terror?.code === 'ENOENT' ||\n\t\t\t\t\t\t\tmessage.includes('not found') ||\n\t\t\t\t\t\t\tmessage.includes('password not found') ||\n\t\t\t\t\t\t\tmessage.includes('item not found') ||\n\t\t\t\t\t\t\tmessage.includes('could not be found');\n\n\t\t\t\t\t\tif (isMissingSecretError) {\n\t\t\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t\t\t'No token found in secure storage for environment: %s',\n\t\t\t\t\t\t\t\tthis.environmentName\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\treturn null;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tthrow new BoxCLIError(\n\t\t\t\t\t\t\t'Failed to delete token from secure storage',\n\t\t\t\t\t\t\terror\n\t\t\t\t\t\t);\n\t\t\t\t\t})\n\t\t\t);\n\t\t}\n\n\t\tpromises.push(\n\t\t\tutilities.unlinkAsync(this.filePath).catch((error) => {\n\t\t\t\tif (error?.code === 'ENOENT') {\n\t\t\t\t\tDEBUG.init(\n\t\t\t\t\t\t'No token file found on disk for environment: %s',\n\t\t\t\t\t\tthis.environmentName\n\t\t\t\t\t);\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tthrow new BoxCLIError('Failed to delete token file', error);\n\t\t\t})\n\t\t);\n\n\t\tPromise.all(promises)\n\t\t\t.then(() => callback())\n\t\t\t.catch((error) =>\n\t\t\t\tcallback(new BoxCLIError('Failed to delete token cache', error))\n\t\t\t);\n\t}\n\n\t/**\n\t * Write the token to storage, compatible with TS SDK\n\t * @param {AccessToken} token The token to write\n\t * @returns {Promise<undefined>} A promise resolving to undefined\n\t */\n\tstore(token) {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tconst acquiredAtMS = Date.now();\n\t\t\tconst tokenInfo = {\n\t\t\t\taccessToken: token.accessToken,\n\t\t\t\taccessTokenTTLMS: token.expiresIn * 1000,\n\t\t\t\trefreshToken: token.refreshToken,\n\t\t\t\tacquiredAtMS,\n\t\t\t};\n\t\t\tthis.write(tokenInfo, (error) => {\n\t\t\t\tif (error) {\n\t\t\t\t\treject(error);\n\t\t\t\t} else {\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n\n\t/**\n\t * Read the token from storage, compatible with TS SDK\n\t * @returns {Promise<undefined | AccessToken>} A promise resolving to the token\n\t */\n\tget() {\n\t\treturn new Promise((resolve, reject) => {\n\t\t\tthis.read((error, tokenInfo) => {\n\t\t\t\tif (error) {\n\t\t\t\t\treject(error);\n\t\t\t\t} else {\n\t\t\t\t\tresolve(tokenInfo.accessToken ? tokenInfo : undefined);\n\t\t\t\t}\n\t\t\t});\n\t\t});\n\t}\n}\n\nmodule.exports = CLITokenCache;\n"
  },
  {
    "path": "src/util.js",
    "content": "'use strict';\n\nconst _ = require('lodash');\nconst BoxCLIError = require('./cli-error');\nconst os = require('node:os');\nconst path = require('node:path');\nconst fs = require('node:fs');\nconst { mkdirp } = require('mkdirp');\n\nconst REQUIRED_CONFIG_VALUES = Object.freeze([\n\t'boxAppSettings.clientID',\n\t'boxAppSettings.clientSecret',\n\t'boxAppSettings.appAuth.publicKeyID',\n\t'boxAppSettings.appAuth.passphrase',\n\t'enterpriseID',\n]);\n\nconst REQUIRED_CONFIG_VALUES_CCG = Object.freeze([\n\t'boxAppSettings.clientID',\n\t'boxAppSettings.clientSecret',\n\t'enterpriseID',\n]);\n\nconst NUMBER_REGEX = /^[-+]?\\d*\\.?\\d+$/u;\nconst UNESCAPED_COMMA_REGEX = /(?<![^\\\\](?:\\\\\\\\)*\\\\),/gu;\nconst UNESCAPED_SUBSCRIPT_REGEX =\n\t/(?<![^\\\\](?:\\\\\\\\)*\\\\)\\[(.*?)(?<![^\\\\](?:\\\\\\\\)*\\\\)\\]/gu;\n\nconst PATH_ESCAPES = Object.freeze({\n\t'/': '~1',\n\t'~': '~0',\n});\nconst DEFAULT_SECRET_KEY = 'clientSecret';\nconst DEFAULT_VISIBLE_SECRET_CHARS = 3;\n\n/**\n * Unescape a string that no longer needs to be escaped with slashes,\n * optionally replacing certain escaped characters with new\n * escape codes.\n *\n * @param {string} str The string to unescape\n * @param {Object} replacements A mapping of escaped characters to new escape codes\n * @returns {string} The unescaped string\n * @private\n */\nfunction unescapeString(str, replacements = {}) {\n\tlet ret = '',\n\t\tchars = [...str];\n\n\twhile (chars.length > 0) {\n\t\tlet char = chars.shift();\n\t\tif (char === '\\\\') {\n\t\t\tlet nextChar = chars.shift();\n\t\t\tnextChar = replacements[nextChar] || nextChar;\n\t\t\tif (nextChar) {\n\t\t\t\tret += nextChar;\n\t\t\t}\n\t\t} else {\n\t\t\tret += char;\n\t\t}\n\t}\n\n\treturn ret;\n}\n\n/**\n * Parse a metadata key into the correct format, including escaping\n * for JSON Patch operations.\n *\n * This method accepts two formats:\n * 1) /path/to\\/from/key => /path/to~1from/key\n * 2) path[to][] => /path/to/-\n *\n * @param {string} value The value to parse as a metadata key\n * @returns {string} The parsed key\n * @private\n */\nfunction parseKey(value) {\n\tif (value.startsWith('/')) {\n\t\t// Treat as path\n\t\treturn unescapeString(value, PATH_ESCAPES);\n\t}\n\t// Treat as key\n\tlet parts = value.split(UNESCAPED_SUBSCRIPT_REGEX);\n\tif (parts.at(-1) === '') {\n\t\tparts = parts.slice(0, -1);\n\t}\n\treturn `/${parts\n\t\t.map((s) => (s ? unescapeString(s, PATH_ESCAPES) : '-'))\n\t\t.join('/')}`;\n}\n\n/**\n * Parses a metadata value from command-line input string\n * to actual value.\n *\n * This method supports the following formats:\n * 1) \"#123.4\" => 123.4\n * 2) \"[foo,bar]\" => [ \"foo\", \"bar\" ]\n * 3) Everything else => unescaped string\n *\n * @param {string} value The command-line value to parse\n * @returns {string|number|string[]} The parsed value\n * @private\n */\nfunction parseValue(value) {\n\tif (value.startsWith('#')) {\n\t\t// Try parsing as number\n\t\tlet valueStr = unescapeString(value.slice(1));\n\t\tif (NUMBER_REGEX.test(valueStr)) {\n\t\t\tlet parsedValue = Number.parseFloat(valueStr);\n\t\t\tif (!Number.isNaN(parsedValue)) {\n\t\t\t\treturn parsedValue;\n\t\t\t}\n\t\t}\n\n\t\t// Parsing failed, fall back to string value\n\t} else if (value.startsWith('[') && value.endsWith(']')) {\n\t\t// Handle as array\n\t\tlet interiorStr = value.slice(1, -1);\n\n\t\tif (interiorStr.length === 0) {\n\t\t\treturn [];\n\t\t}\n\n\t\treturn interiorStr\n\t\t\t.split(UNESCAPED_COMMA_REGEX)\n\t\t\t.map((el) => unescapeString(el));\n\t}\n\n\t// No other parsing applied; treat as string\n\treturn unescapeString(value);\n}\n\n/**\n * Parses a metadata command line string into the correct operation\n * object.\n *\n * This method performs the following transformations:\n * 1) key=value => {path: '/key', value: 'value'}\n * 2) key1>key2 => {from: '/key1', path: '/key2'}\n *\n * @param {string} input The input string from the command line\n * @returns {Object} The parsed metadata operation object\n * @private\n */\nfunction parseMetadataString(input) {\n\tlet chars = [...input];\n\tlet op = {};\n\n\t// Find the splitting point, if one exists\n\tlet splitIndex = chars.findIndex((char, index, arr) => {\n\t\tif (char === '>' || char === '=') {\n\t\t\tlet escaped = false;\n\t\t\tfor (let i = index - 1; i >= 0; i--) {\n\t\t\t\tif (arr[i] === '\\\\') {\n\t\t\t\t\tescaped = !escaped;\n\t\t\t\t} else {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!escaped) {\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t});\n\n\tif (splitIndex === -1) {\n\t\t// This is just a key, return it\n\t\top.path = parseKey(chars.join(''));\n\t\treturn op;\n\t}\n\n\tlet separator = chars[splitIndex];\n\tif (separator === '>') {\n\t\top.from = parseKey(chars.slice(0, splitIndex).join(''));\n\t\top.path = parseKey(chars.slice(splitIndex + 1).join(''));\n\t} else {\n\t\top.path = parseKey(chars.slice(0, splitIndex).join(''));\n\t\top.value = parseValue(chars.slice(splitIndex + 1).join(''));\n\t}\n\n\treturn op;\n}\n\n/**\n * Parse a string into a JSON object\n *\n * @param {string} inputString The string to parse\n * @param {string[]} keys The keys to parse from the string\n * @returns {Object} The parsed object\n */\nfunction parseStringToObject(inputString, keys) {\n\tconst result = {};\n\n\twhile (inputString.length > 0) {\n\t\tinputString = inputString.trim();\n\t\tlet parsedKey = inputString.split('=')[0];\n\t\tinputString = inputString.slice(\n\t\t\tMath.max(0, inputString.indexOf('=') + 1)\n\t\t);\n\n\t\t// Find the next key or the end of the string\n\t\tlet nextKeyIndex = inputString.length;\n\t\tfor (let key of keys) {\n\t\t\tlet keyIndex = inputString.indexOf(key);\n\t\t\tif (keyIndex !== -1 && keyIndex < nextKeyIndex) {\n\t\t\t\tnextKeyIndex = keyIndex;\n\t\t\t}\n\t\t}\n\n\t\tlet parsedValue = inputString\n\t\t\t.slice(0, Math.max(0, nextKeyIndex))\n\t\t\t.trim();\n\t\tif (parsedValue.endsWith(',') && nextKeyIndex !== inputString.length) {\n\t\t\tparsedValue = parsedValue.slice(\n\t\t\t\t0,\n\t\t\t\tMath.max(0, parsedValue.length - 1)\n\t\t\t);\n\t\t}\n\t\tif (parsedValue.startsWith('\"') && parsedValue.endsWith('\"')) {\n\t\t\tparsedValue = parsedValue.slice(1, -1);\n\t\t}\n\n\t\tif (!keys.includes(parsedKey)) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t`Invalid key '${parsedKey}'. Valid keys are ${keys.join(', ')}`\n\t\t\t);\n\t\t}\n\n\t\tresult[parsedKey] = parsedValue;\n\t\tinputString = inputString.slice(Math.max(0, nextKeyIndex));\n\t}\n\treturn result;\n}\n\n/**\n * Check if directory exists and creates it if shouldCreate flag was passed.\n *\n * @param {string} dirPath Directory path to check and create\n * @param {boolean} shouldCreate Flag indicating if the directory should be created\n * @returns {Promise<void>} empty promise\n * @throws BoxCLIError\n */\nasync function checkDir(dirPath, shouldCreate) {\n\tif (!fs.existsSync(dirPath)) {\n\t\tif (shouldCreate) {\n\t\t\tawait mkdirp(dirPath);\n\t\t} else {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t`The ${dirPath} path does not exist. Either create it, or pass the --create-path flag set to true`\n\t\t\t);\n\t\t}\n\t}\n}\n\nasync function readFileAsync(path, options) {\n\treturn new Promise((resolve, reject) => {\n\t\tfs.readFile(path, options || {}, (err, result) => {\n\t\t\tif (err) {\n\t\t\t\treturn reject(err);\n\t\t\t}\n\t\t\treturn resolve(result);\n\t\t});\n\t});\n}\n\nasync function writeFileAsync(file, data, options) {\n\treturn new Promise((resolve, reject) => {\n\t\tfs.writeFile(file, data, options || {}, (err, result) => {\n\t\t\tif (err) {\n\t\t\t\treturn reject(err);\n\t\t\t}\n\t\t\treturn resolve(result);\n\t\t});\n\t});\n}\n\nasync function readdirAsync(path, options) {\n\treturn new Promise((resolve, reject) => {\n\t\tfs.readdir(path, options || {}, (err, result) => {\n\t\t\tif (err) {\n\t\t\t\treturn reject(err);\n\t\t\t}\n\t\t\treturn resolve(result);\n\t\t});\n\t});\n}\n\nasync function unlinkAsync(path) {\n\treturn new Promise((resolve, reject) => {\n\t\tfs.unlink(path, (err, result) => {\n\t\t\tif (err) {\n\t\t\t\treturn reject(err);\n\t\t\t}\n\t\t\treturn resolve(result);\n\t\t});\n\t});\n}\n\nfunction maskSecret(secret, visibleChars = DEFAULT_VISIBLE_SECRET_CHARS) {\n\tconst normalizedVisibleChars =\n\t\t_.isInteger(visibleChars) && visibleChars >= 0\n\t\t\t? visibleChars\n\t\t\t: DEFAULT_VISIBLE_SECRET_CHARS;\n\t\t\t\n\tif (!_.isString(secret) || secret.length <= normalizedVisibleChars) {\n\t\treturn '*'.repeat(normalizedVisibleChars);\n\t}\n\n\treturn `${'*'.repeat(secret.length - normalizedVisibleChars)}${secret.slice(-normalizedVisibleChars)}`;\n}\n\nfunction maskObjectValuesByKey(\n\tvalue,\n\tkeyToMask = DEFAULT_SECRET_KEY,\n\tvisibleChars = DEFAULT_VISIBLE_SECRET_CHARS\n) {\n\tif (_.isArray(value)) {\n\t\treturn value.map((item) =>\n\t\t\tmaskObjectValuesByKey(item, keyToMask, visibleChars)\n\t\t);\n\t}\n\n\tif (_.isPlainObject(value)) {\n\t\treturn _.mapValues(value, (objectValue, key) => {\n\t\t\tif (key === keyToMask && !_.isNil(objectValue)) {\n\t\t\t\treturn maskSecret(objectValue, visibleChars);\n\t\t\t}\n\n\t\t\treturn maskObjectValuesByKey(objectValue, keyToMask, visibleChars);\n\t\t});\n\t}\n\n\treturn value;\n}\n\nmodule.exports = {\n\t/**\n\t * Validates the a configuration object has all required properties\n\t * @param {Object} configObj The config object to validate\n\t * @param {boolean} isCCG Whether the config object is used for CCG auth\n\t * @returns {void}\n\t * @throws BoxCLIError\n\t */\n\tvalidateConfigObject(configObj, isCCG) {\n\t\tlet checkProp = _.propertyOf(configObj);\n\t\tlet requiredConfigValues = isCCG\n\t\t\t? REQUIRED_CONFIG_VALUES_CCG\n\t\t\t: REQUIRED_CONFIG_VALUES;\n\t\tlet missingProp = requiredConfigValues.find((key) => !checkProp(key));\n\n\t\tif (missingProp) {\n\t\t\tthrow new BoxCLIError(`Config object missing key ${missingProp}`);\n\t\t}\n\t},\n\n\t/**\n\t * Parses a path argument or flag value into a full absolute path\n\t *\n\t * @param {string} value The raw path string from the command line flag or arg\n\t * @returns {string} The resolved absolute path\n\t */\n\tparsePath(value) {\n\t\t// Check for homedir and expand if necessary\n\t\t// @NOTE: This can occur when the user passes a path via --flag=\"~/my-stuff\" syntax, since the shell\n\t\t// doesn't get a chance to expand the tilde\n\t\tvalue = value.replace(\n\t\t\t/^~(\\/|\\\\|$)/u,\n\t\t\t(match, ending) => os.homedir() + ending\n\t\t);\n\t\treturn path.resolve(value);\n\t},\n\n\t/**\n\t * Unescape slashes from the given string.\n\t *\n\t * @param {string} value The raw string which can contains escaped slashes\n\t * @returns {string} A string with unescaped escaping in newline and tab characters.\n\t */\n\tunescapeSlashes(value) {\n\t\ttry {\n\t\t\treturn JSON.parse(`\"${value}\"`);\n\t\t} catch {\n\t\t\treturn value;\n\t\t}\n\t},\n\n\t/**\n\t * Parses the key=val string format for metadata into an object {key: val}\n\t *\n\t * @param {string} value The string containing metadata key and value\n\t * @returns {Object} The parsed metadata key and value\n\t */\n\tparseMetadata(value) {\n\t\tlet op = parseMetadataString(value);\n\t\tif (!Object.hasOwn(op, 'path') || !Object.hasOwn(op, 'value')) {\n\t\t\tthrow new BoxCLIError('Metadata must be in the form key=value');\n\t\t}\n\n\t\tlet pathSegments = op.path.slice(1).split('/');\n\t\tif (pathSegments.length !== 1) {\n\t\t\tthrow new BoxCLIError(\n\t\t\t\t`Metadata value must be assigned to a top-level key, instead got ${op.path}`\n\t\t\t);\n\t\t}\n\n\t\tlet key = pathSegments[0];\n\n\t\treturn { [key]: op.value };\n\t},\n\n\t/**\n\t * Parses strings like key=value or key1>key2 into objects\n\t * used to help define JSON patch operations.\n\t *\n\t * key=value => {path: key, value: value}\n\t * key1>key2 => {from: key1, path: key2}\n\t * other => {path: other}\n\t *\n\t * @param {string} value The input string\n\t * @returns {Object} The parsed operation object\n\t */\n\tparseMetadataOp(value) {\n\t\treturn parseMetadataString(value);\n\t},\n\tmaskSecret,\n\tmaskObjectValuesByKey,\n\tparseStringToObject,\n\tcheckDir,\n\treadFileAsync,\n\twriteFileAsync,\n\treaddirAsync,\n\tunlinkAsync,\n};\n"
  },
  {
    "path": "test/.eslintrc.yml",
    "content": "---\n\nenv:\n    mocha: true\n\nrules:\n    # JSDoc is not required in test files, obviously\n    require-jsdoc: off\n    # We often require a file AFTER mocking its dependencies in tests\n    global-require: off\n    # Mocha doesn't like arrow functions\n    prefer-arrow-callback: off\n    # Tests don't need to return from .then() with asserts\n    promise/always-return: off\n"
  },
  {
    "path": "test/box-command.test.js",
    "content": "'use strict';\n\nconst { assert } = require('chai');\nconst BoxCommand = require('../src/box-command');\nconst sinon = require('sinon');\nconst leche = require('leche');\nconst { test } = require('@oclif/test');\nconst debug = require('debug');\nconst { TEST_API_ROOT, isWin } = require('./helpers/test-helper');\n\ndescribe('BoxCommand', function () {\n\tconst sandbox = sinon.createSandbox();\n\n\tafterEach(function () {\n\t\tsandbox.verifyAndRestore();\n\t});\n\n\tdescribe('Command', function () {\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get('/2.0/users/me').reply(200, {})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command(['users:get', 'me', '--token=test', '--verbose'])\n\t\t\t.it(\n\t\t\t\t'should enable framework debugging when verbose flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tdebug.disable();\n\t\t\t\t\tconst debugLines = context.stderr.split('\\n');\n\t\t\t\t\tassert.include(debugLines[0], 'box:@box/cli:hooks:init');\n\t\t\t\t\tassert.include(debugLines[1], 'box-cli:init');\n\t\t\t\t}\n\t\t\t)\n\t\t\t.timeout(10_000);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/users/me')\n\t\t\t\t.matchHeader('X-Box-UA', /client=box-cli\\/\\d+\\.\\d+\\.\\d+/u)\n\t\t\t\t.matchHeader('User-Agent', /^Box CLI v\\d+\\.\\d+\\.\\d+$/u)\n\t\t\t\t.reply(200, {})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command(['users:get', 'me', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should send correct analytics and identification headers with API requests'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/collaborations').reply(200, {})\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:collaborations:add',\n\t\t\t\t'0',\n\t\t\t\t'--previewer',\n\t\t\t\t'--token=test',\n\t\t\t\t'--save',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should save output to file named with valid characters',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t'folders-collaborations-add'\n\t\t\t\t\t);\n\t\t\t\t\tconst stderr = isWin()\n\t\t\t\t\t\t? context.stderr.replace(':', '')\n\t\t\t\t\t\t: context.stderr;\n\t\t\t\t\tassert.notInclude(stderr, ':');\n\t\t\t\t}\n\t\t\t);\n\n\t\tdescribe('As-User', function () {\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/users/me')\n\t\t\t\t\t.matchHeader('As-user', '12345')\n\t\t\t\t\t.reply(200, {})\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.stderr()\n\t\t\t\t.command(['users:get', 'me', '--token=test', '--as-user=12345'])\n\t\t\t\t.it('should send as-user header when --as-user flag is passed');\n\t\t});\n\t});\n\n\tdescribe('normalizeDateString()', function () {\n\t\tbeforeEach(function () {\n\t\t\t// Start clocks at 2018-07-13T12:00:00 UTC for all tests\n\t\t\tsandbox.useFakeTimers(1_531_508_400_000);\n\t\t});\n\n\t\tleche.withData(\n\t\t\t{\n\t\t\t\t'now shorthand': ['now', '2018-07-13T19:00:00+00:00'],\n\t\t\t\t'zero seconds shorthand': ['0s', '2018-07-13T19:00:00+00:00'],\n\t\t\t\t'zero minutes shorthand': ['0m', '2018-07-13T19:00:00+00:00'],\n\t\t\t\t'zero hours shorthand': ['0h', '2018-07-13T19:00:00+00:00'],\n\t\t\t\t'zero days shorthand': ['0d', '2018-07-13T19:00:00+00:00'],\n\t\t\t\t'zero weeks shorthand': ['0w', '2018-07-13T19:00:00+00:00'],\n\t\t\t\t'zero months shorthand': ['0M', '2018-07-13T19:00:00+00:00'],\n\t\t\t\t'zero years shorthand': ['0y', '2018-07-13T19:00:00+00:00'],\n\t\t\t\t'adding one second': ['1s', '2018-07-13T19:00:01+00:00'],\n\t\t\t\t'adding one minute': ['1m', '2018-07-13T19:01:00+00:00'],\n\t\t\t\t'adding one hour': ['1h', '2018-07-13T20:00:00+00:00'],\n\t\t\t\t'adding one day': ['1d', '2018-07-14T19:00:00+00:00'],\n\t\t\t\t'adding one week': ['1w', '2018-07-20T19:00:00+00:00'],\n\t\t\t\t'adding one month': ['1M', '2018-08-13T19:00:00+00:00'],\n\t\t\t\t'adding one year': ['1y', '2019-07-13T19:00:00+00:00'],\n\t\t\t\t'subtracting one second': ['-1s', '2018-07-13T18:59:59+00:00'],\n\t\t\t\t'subtracting one minute': ['-1m', '2018-07-13T18:59:00+00:00'],\n\t\t\t\t'subtracting one hour': ['-1h', '2018-07-13T18:00:00+00:00'],\n\t\t\t\t'subtracting one day': ['-1d', '2018-07-12T19:00:00+00:00'],\n\t\t\t\t'subtracting one week': ['-1w', '2018-07-06T19:00:00+00:00'],\n\t\t\t\t'subtracting one month': ['-1M', '2018-06-13T19:00:00+00:00'],\n\t\t\t\t'subtracting one year': ['-1y', '2017-07-13T19:00:00+00:00'],\n\t\t\t\t// 'adding time across time zone change': [\n\t\t\t\t// \t'4M',\n\t\t\t\t// \t'2018-11-13T20:00:00+00:00'\n\t\t\t\t// ],\n\t\t\t\t// 'subtracting time across time zone change': [\n\t\t\t\t// \t'-5M',\n\t\t\t\t// \t'2018-02-13T20:00:00+00:00'\n\t\t\t\t// ],\n\t\t\t\t'exact time': [\n\t\t\t\t\t'2018-01-01T00:00:00-08:00',\n\t\t\t\t\t'2018-01-01T08:00:00+00:00',\n\t\t\t\t],\n\t\t\t\t'exact time in different timezone': [\n\t\t\t\t\t'2018-01-01T02:00:00-06:00',\n\t\t\t\t\t'2018-01-01T08:00:00+00:00',\n\t\t\t\t],\n\t\t\t\t'exact time with Z offset': [\n\t\t\t\t\t'2018-01-01T08:00:00Z',\n\t\t\t\t\t'2018-01-01T08:00:00+00:00',\n\t\t\t\t],\n\t\t\t\t'exact time with UTC offset': [\n\t\t\t\t\t'2018-01-01T08:00:00+00:00',\n\t\t\t\t\t'2018-01-01T08:00:00+00:00',\n\t\t\t\t],\n\t\t\t\t// 'date only': [\n\t\t\t\t// \t'2018-07-01',\n\t\t\t\t// \t'2018-07-01T00:00:00+00:00'\n\t\t\t\t// ],\n\t\t\t\t'timestamp string': ['1535336043', '2018-08-27T02:14:03+00:00'],\n\t\t\t\t'a combination of positive offset shorthands': [\n\t\t\t\t\t'1d30s13h',\n\t\t\t\t\t'2018-07-15T08:00:30+00:00',\n\t\t\t\t],\n\t\t\t\t// 'a combination of negative offset shorthands': [\n\t\t\t\t// \t'-1y5M30s13h',\n\t\t\t\t// \t'2017-02-13T05:59:30+00:00'\n\t\t\t\t// ]\n\t\t\t},\n\t\t\tfunction (input, expectedOutput) {\n\t\t\t\tit('should return the full RFC3339 timestamp for the given time', function () {\n\t\t\t\t\tlet dateTime = BoxCommand.normalizeDateString(input);\n\t\t\t\t\tassert.equal(dateTime, expectedOutput);\n\t\t\t\t});\n\t\t\t}\n\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/ai.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { TEST_API_ROOT, getFixture } = require('../helpers/test-helper');\n\nfunction getAgentInRequestBody(type) {\n\tconst agent = {\n\t\ttype,\n\t\tbasic_text: {\n\t\t\tllm_endpoint_params: {\n\t\t\t\ttype: 'openai_params',\n\t\t\t\tfrequency_penalty: 1.5,\n\t\t\t\tpresence_penalty: 1.5,\n\t\t\t\tstop: '<|im_end|>',\n\t\t\t\ttemperature: 0,\n\t\t\t\ttop_p: 1,\n\t\t\t},\n\t\t\tmodel: 'azure__openai__gpt_4o_mini',\n\t\t\tnum_tokens_for_completion: 8400,\n\t\t\tprompt_template:\n\t\t\t\t'It is, consider these travel options and answer the.',\n\t\t\tsystem_message:\n\t\t\t\t'You are a helpful travel assistant specialized in budget travel',\n\t\t},\n\t\tlong_text: {\n\t\t\tembeddings: {\n\t\t\t\tmodel: 'azure__openai__text_embedding_ada_002',\n\t\t\t\tstrategy: {\n\t\t\t\t\tid: 'basic',\n\t\t\t\t\tnum_tokens_per_chunk: 64,\n\t\t\t\t},\n\t\t\t},\n\t\t\tllm_endpoint_params: {\n\t\t\t\ttype: 'openai_params',\n\t\t\t\tfrequency_penalty: 1.5,\n\t\t\t\tpresence_penalty: 1.5,\n\t\t\t\tstop: '<|im_end|>',\n\t\t\t\ttemperature: 0,\n\t\t\t\ttop_p: 1,\n\t\t\t},\n\t\t\tmodel: 'azure__openai__gpt_4o_mini',\n\t\t\tnum_tokens_for_completion: 8400,\n\t\t\tprompt_template:\n\t\t\t\t'It is , consider these travel options and answer the.',\n\t\t\tsystem_message:\n\t\t\t\t'You are a helpful travel assistant specialized in budget travel',\n\t\t},\n\t};\n\treturn agent;\n}\n\ndescribe('AI', function () {\n\tdescribe('ai:ask', function () {\n\t\tconst expectedRequestBody = {\n\t\t\titems: [\n\t\t\t\t{\n\t\t\t\t\tid: '12345',\n\t\t\t\t\ttype: 'file',\n\t\t\t\t\tcontent: 'one,two,three',\n\t\t\t\t},\n\t\t\t],\n\t\t\tmode: 'single_item_qa',\n\t\t\tprompt: 'What is the status of this document?',\n\t\t};\n\n\t\tconst expectedResponseBody = {\n\t\t\tanswer: 'The document is currently in review and awaiting approval.',\n\t\t\tcreated_at: '2024-07-09T11:29:46.835Z',\n\t\t\tcompletion_reason: 'done',\n\t\t\tai_agent_info: {\n\t\t\t\tmodels: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'google__gemini_2_0_flash_001',\n\t\t\t\t\t\tprovider: 'google',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tprocessor: 'basic_text',\n\t\t\t},\n\t\t};\n\n\t\tconst fixture = getFixture('ai/post_ai_ask_response');\n\t\tconst yamlFixture = getFixture('ai/post_ai_ask_response_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/ai/ask', expectedRequestBody)\n\t\t\t\t.reply(200, expectedResponseBody)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:ask',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--prompt',\n\t\t\t\t'What is the status of this document?',\n\t\t\t\t'--raw-json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should output the raw response when --raw-json is passed', (context) => {\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), expectedResponseBody);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/ai/ask', expectedRequestBody)\n\t\t\t\t.reply(200, expectedResponseBody)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:ask',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--prompt',\n\t\t\t\t'What is the status of this document?',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send the correct request and output the response (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/ai/ask', expectedRequestBody)\n\t\t\t\t.reply(200, expectedResponseBody)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:ask',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--prompt',\n\t\t\t\t'What is the status of this document?',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send the correct request and output the response (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlFixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('ai:ask with ai_agent', function () {\n\t\tconst expectedRequestBody = {\n\t\t\titems: [\n\t\t\t\t{\n\t\t\t\t\tid: '12345',\n\t\t\t\t\ttype: 'file',\n\t\t\t\t\tcontent: 'one,two,three',\n\t\t\t\t},\n\t\t\t],\n\t\t\tmode: 'single_item_qa',\n\t\t\tprompt: 'What is the status of this document?',\n\t\t\tai_agent: getAgentInRequestBody('ai_agent_ask'),\n\t\t};\n\n\t\tconst expectedResponseBody = {\n\t\t\tanswer: 'The document is currently in review and awaiting approval.',\n\t\t\tcreated_at: '2024-07-09T11:29:46.835Z',\n\t\t\tcompletion_reason: 'done',\n\t\t\tai_agent_info: {\n\t\t\t\tmodels: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'google__gemini_2_0_flash_001',\n\t\t\t\t\t\tprovider: 'google',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tprocessor: 'basic_text',\n\t\t\t},\n\t\t};\n\n\t\tconst fixture = getFixture('ai/post_ai_ask_response');\n\t\tconst yamlFixture = getFixture('ai/post_ai_ask_response_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) => {\n\t\t\tapi.post('/2.0/ai/ask', expectedRequestBody).reply(\n\t\t\t\t200,\n\t\t\t\texpectedResponseBody\n\t\t\t);\n\t\t})\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:ask',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--prompt',\n\t\t\t\t'What is the status of this document?',\n\t\t\t\t'--ai-agent',\n\t\t\t\t'{\"type\":\"ai_agent_ask\",\"basicText\":{\"llmEndpointParams\":{\"type\":\"openai_params\",\"frequencyPenalty\": 1.5,\"presencePenalty\": 1.5,\"stop\": \"<|im_end|>\",\"temperature\": 0,\"topP\": 1},\"model\": \"azure__openai__gpt_4o_mini\",\"numTokensForCompletion\": 8400,\"promptTemplate\": \"It is, consider these travel options and answer the.\",\"systemMessage\": \"You are a helpful travel assistant specialized in budget travel\"},\"longText\":{\"embeddings\":{ \"model\": \"azure__openai__text_embedding_ada_002\",\"strategy\":{\"id\": \"basic\",\"numTokensPerChunk\": 64}},\"llmEndpointParams\":{\"type\":\"openai_params\",\"frequencyPenalty\": 1.5,\"presencePenalty\": 1.5,\"stop\": \"<|im_end|>\",\"temperature\": 0,\"topP\": 1},\"model\":\"azure__openai__gpt_4o_mini\",\"numTokensForCompletion\":8400,\"promptTemplate\":\"It is , consider these travel options and answer the.\",\"systemMessage\":\"You are a helpful travel assistant specialized in budget travel\"}}',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\n\t\t\t.it(\n\t\t\t\t'should send the correct request and output the response (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) => {\n\t\t\tapi.post('/2.0/ai/ask', expectedRequestBody).reply(\n\t\t\t\t200,\n\t\t\t\texpectedResponseBody\n\t\t\t);\n\t\t})\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:ask',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--prompt',\n\t\t\t\t'What is the status of this document?',\n\t\t\t\t'--ai-agent',\n\t\t\t\t'{\"type\":\"ai_agent_ask\",\"basicText\":{\"llmEndpointParams\":{\"type\":\"openai_params\",\"frequencyPenalty\": 1.5,\"presencePenalty\": 1.5,\"stop\": \"<|im_end|>\",\"temperature\": 0,\"topP\": 1},\"model\": \"azure__openai__gpt_4o_mini\",\"numTokensForCompletion\": 8400,\"promptTemplate\": \"It is, consider these travel options and answer the.\",\"systemMessage\": \"You are a helpful travel assistant specialized in budget travel\"},\"longText\":{\"embeddings\":{ \"model\": \"azure__openai__text_embedding_ada_002\",\"strategy\":{\"id\": \"basic\",\"numTokensPerChunk\": 64}},\"llmEndpointParams\":{\"type\":\"openai_params\",\"frequencyPenalty\": 1.5,\"presencePenalty\": 1.5,\"stop\": \"<|im_end|>\",\"temperature\": 0,\"topP\": 1},\"model\":\"azure__openai__gpt_4o_mini\",\"numTokensForCompletion\":8400,\"promptTemplate\":\"It is , consider these travel options and answer the.\",\"systemMessage\":\"You are a helpful travel assistant specialized in budget travel\"}}',\n\t\t\t\t'--token=test',\n\t\t\t])\n\n\t\t\t.it(\n\t\t\t\t'should send the correct request and output the response (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlFixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('ai:text-gen', function () {\n\t\tconst expectedRequestBody = {\n\t\t\tprompt: 'What is the status of this document?',\n\t\t\titems: [{ id: '12345', type: 'file', content: 'one,two,three' }],\n\t\t\tdialogue_history: [\n\t\t\t\t{\n\t\t\t\t\tprompt: 'What is the status of this document, signatures?',\n\t\t\t\t\tanswer: 'It is in review, waiting for signatures.',\n\t\t\t\t\tcreated_at: '2024-07-09T11:29:46+00:00',\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t\tconst expectedResponseBody = {\n\t\t\tanswer: 'The document is currently in review and awaiting approval.',\n\t\t\tcreated_at: '2024-07-09T11:29:46.835Z',\n\t\t\tcompletion_reason: 'done',\n\t\t};\n\t\tconst fixture = getFixture('ai/post_ai_text_gen_response');\n\t\tconst yamlFixture = getFixture('ai/post_ai_text_gen_response_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/ai/text_gen', expectedRequestBody)\n\t\t\t\t.reply(200, expectedResponseBody)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:text-gen',\n\t\t\t\t'--dialogue-history',\n\t\t\t\t'prompt=What is the status of this document, signatures?,answer=It is in review, waiting for signatures.,created-at=2024-07-09T11:29:46.835Z',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--prompt',\n\t\t\t\t'What is the status of this document?',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send the correct request and output the response (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/ai/text_gen', expectedRequestBody)\n\t\t\t\t.reply(200, expectedResponseBody)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:text-gen',\n\t\t\t\t'--dialogue-history',\n\t\t\t\t'prompt=What is the status of this document, signatures?,answer=It is in review, waiting for signatures.,created-at=2024-07-09T11:29:46.835Z',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--prompt',\n\t\t\t\t'What is the status of this document?',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send the correct request and output the response (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlFixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('ai:extract', function () {\n\t\tconst expectedRequestBody = {\n\t\t\tprompt: 'firstName, lastName, location, yearOfBirth, company',\n\t\t\titems: [\n\t\t\t\t{\n\t\t\t\t\tid: '12345',\n\t\t\t\t\ttype: 'file',\n\t\t\t\t\tcontent: 'one,two,three',\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t\tconst expectedResponseBody = {\n\t\t\tanswer: '{\"firstName\": \"John\", \"lastName\": \"Doe\", \"location\": \"San Francisco\", \"yearOfBirth\": \"1990\", \"company\": \"Box\"}',\n\t\t\tcreated_at: '2025-05-02T14:51:30.567Z',\n\t\t\tcompletion_reason: 'done',\n\t\t\tai_agent_info: {\n\t\t\t\tmodels: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'google__gemini_2_0_flash_001',\n\t\t\t\t\t\tprovider: 'google',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tprocessor: 'basic_text',\n\t\t\t},\n\t\t};\n\n\t\tconst fixture = getFixture('ai/post_ai_extract_response');\n\t\tconst yamlFixture = getFixture('ai/post_ai_extract_response_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) => {\n\t\t\tapi.post('/2.0/ai/extract', expectedRequestBody).reply(\n\t\t\t\t200,\n\t\t\t\texpectedResponseBody\n\t\t\t);\n\t\t})\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:extract',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--prompt',\n\t\t\t\t'firstName, lastName, location, yearOfBirth, company',\n\t\t\t\t'--raw-json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\n\t\t\t.it(\n\t\t\t\t'should output the raw response when --raw-json is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), expectedResponseBody);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) => {\n\t\t\tapi.post('/2.0/ai/extract', expectedRequestBody).reply(\n\t\t\t\t200,\n\t\t\t\texpectedResponseBody\n\t\t\t);\n\t\t})\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:extract',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--prompt',\n\t\t\t\t'firstName, lastName, location, yearOfBirth, company',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\n\t\t\t.it(\n\t\t\t\t'should send the correct request and output the response (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) => {\n\t\t\tapi.post('/2.0/ai/extract', expectedRequestBody).reply(\n\t\t\t\t200,\n\t\t\t\texpectedResponseBody\n\t\t\t);\n\t\t})\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:extract',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--prompt',\n\t\t\t\t'firstName, lastName, location, yearOfBirth, company',\n\t\t\t\t'--token=test',\n\t\t\t])\n\n\t\t\t.it(\n\t\t\t\t'should send the correct request and output the response (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlFixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('ai:extract-structured', function () {\n\t\tconst expectedRequestBody = {\n\t\t\titems: [\n\t\t\t\t{\n\t\t\t\t\tid: '12345',\n\t\t\t\t\ttype: 'file',\n\t\t\t\t\tcontent: 'one,two,three',\n\t\t\t\t},\n\t\t\t],\n\t\t\tfields: [\n\t\t\t\t{\n\t\t\t\t\tkey: 'firstName',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdescription: 'Person first name',\n\t\t\t\t\tprompt: 'What is the first name?',\n\t\t\t\t\tdisplayName: 'First name',\n\t\t\t\t\toptions: [{ key: 'First Name' }, { key: 'Last Name' }],\n\t\t\t\t},\n\t\t\t],\n\t\t};\n\t\tconst expectedResponseBody = {\n\t\t\tanswer: {\n\t\t\t\tfirstName: 'John',\n\t\t\t\tlastName: 'Doe',\n\t\t\t},\n\t\t\tcreated_at: '2025-04-29T07:25:24.366-07:00',\n\t\t\tcompletion_reason: 'done',\n\t\t\tai_agent_info: {\n\t\t\t\tmodels: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'google__gemini_2_0_flash_001',\n\t\t\t\t\t\tprovider: 'google',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tprocessor: 'basic_text',\n\t\t\t},\n\t\t};\n\n\t\tconst fixture = getFixture('ai/post_ai_extract_structured_response');\n\t\tconst yamlFixture = getFixture(\n\t\t\t'ai/post_ai_extract_structured_response_yaml.txt'\n\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) => {\n\t\t\tapi.post('/2.0/ai/extract_structured', expectedRequestBody).reply(\n\t\t\t\t200,\n\t\t\t\texpectedResponseBody\n\t\t\t);\n\t\t})\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:extract-structured',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--fields=key=firstName,type=string,description=Person first name,prompt=What is the first name?,displayName=First name,options=First Name; Last Name',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\n\t\t\t.it(\n\t\t\t\t'should send the correct request and output the response (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) => {\n\t\t\tapi.post('/2.0/ai/extract_structured', expectedRequestBody).reply(\n\t\t\t\t200,\n\t\t\t\texpectedResponseBody\n\t\t\t);\n\t\t})\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:extract-structured',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--fields=key=firstName,type=string,description=Person first name,prompt=What is the first name?,displayName=First name,options=First Name;Last Name',\n\t\t\t\t'--token=test',\n\t\t\t])\n\n\t\t\t.it(\n\t\t\t\t'should send the correct request and output the response (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlFixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('ai:extract-structured with ai_agent', function () {\n\t\tconst expectedRequestBody = {\n\t\t\titems: [\n\t\t\t\t{\n\t\t\t\t\tid: '12345',\n\t\t\t\t\ttype: 'file',\n\t\t\t\t\tcontent: 'one,two,three',\n\t\t\t\t},\n\t\t\t],\n\t\t\tfields: [\n\t\t\t\t{\n\t\t\t\t\tkey: 'firstName',\n\t\t\t\t\ttype: 'string',\n\t\t\t\t\tdescription: 'Person first name',\n\t\t\t\t\tprompt: 'What is the first name?',\n\t\t\t\t\tdisplayName: 'First name',\n\t\t\t\t\toptions: [{ key: 'First Name' }],\n\t\t\t\t},\n\t\t\t],\n\t\t\tai_agent: getAgentInRequestBody('ai_agent_extract_structured'),\n\t\t};\n\t\tconst expectedResponseBody = {\n\t\t\tanswer: {\n\t\t\t\tfirstName: 'John',\n\t\t\t\tlastName: 'Doe',\n\t\t\t},\n\t\t\tcreated_at: '2025-04-29T07:25:24.366-07:00',\n\t\t\tcompletion_reason: 'done',\n\t\t\tai_agent_info: {\n\t\t\t\tmodels: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'google__gemini_2_0_flash_001',\n\t\t\t\t\t\tprovider: 'google',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tprocessor: 'basic_text',\n\t\t\t},\n\t\t};\n\n\t\tconst fixture = getFixture('ai/post_ai_extract_structured_response');\n\t\tconst yamlFixture = getFixture(\n\t\t\t'ai/post_ai_extract_structured_response_yaml.txt'\n\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) => {\n\t\t\tapi.post('/2.0/ai/extract_structured', expectedRequestBody).reply(\n\t\t\t\t200,\n\t\t\t\texpectedResponseBody\n\t\t\t);\n\t\t})\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:extract-structured',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--fields=key=firstName,type=string,description=Person first name,prompt=What is the first name?,displayName=First name,options=First Name',\n\t\t\t\t'--ai-agent',\n\t\t\t\t'{\"type\":\"ai_agent_extract_structured\",\"basicText\":{\"llmEndpointParams\":{\"type\":\"openai_params\",\"frequencyPenalty\": 1.5,\"presencePenalty\": 1.5,\"stop\": \"<|im_end|>\",\"temperature\": 0,\"topP\": 1},\"model\": \"azure__openai__gpt_4o_mini\",\"numTokensForCompletion\": 8400,\"promptTemplate\": \"It is, consider these travel options and answer the.\",\"systemMessage\": \"You are a helpful travel assistant specialized in budget travel\"},\"longText\":{\"embeddings\":{ \"model\": \"azure__openai__text_embedding_ada_002\",\"strategy\":{\"id\": \"basic\",\"numTokensPerChunk\": 64}},\"llmEndpointParams\":{\"type\":\"openai_params\",\"frequencyPenalty\": 1.5,\"presencePenalty\": 1.5,\"stop\": \"<|im_end|>\",\"temperature\": 0,\"topP\": 1},\"model\":\"azure__openai__gpt_4o_mini\",\"numTokensForCompletion\":8400,\"promptTemplate\":\"It is , consider these travel options and answer the.\",\"systemMessage\":\"You are a helpful travel assistant specialized in budget travel\"}}',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\n\t\t\t.it(\n\t\t\t\t'should send the correct request and output the response (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) => {\n\t\t\tapi.post('/2.0/ai/extract_structured', expectedRequestBody).reply(\n\t\t\t\t200,\n\t\t\t\texpectedResponseBody\n\t\t\t);\n\t\t})\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:extract-structured',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--fields=key=firstName,type=string,description=Person first name,prompt=What is the first name?,displayName=First name,options=First Name',\n\t\t\t\t'--ai-agent',\n\t\t\t\t'{\"type\":\"ai_agent_extract_structured\",\"basicText\":{\"llmEndpointParams\":{\"type\":\"openai_params\",\"frequencyPenalty\": 1.5,\"presencePenalty\": 1.5,\"stop\": \"<|im_end|>\",\"temperature\": 0,\"topP\": 1},\"model\": \"azure__openai__gpt_4o_mini\",\"numTokensForCompletion\": 8400,\"promptTemplate\": \"It is, consider these travel options and answer the.\",\"systemMessage\": \"You are a helpful travel assistant specialized in budget travel\"},\"longText\":{\"embeddings\":{ \"model\": \"azure__openai__text_embedding_ada_002\",\"strategy\":{\"id\": \"basic\",\"numTokensPerChunk\": 64}},\"llmEndpointParams\":{\"type\":\"openai_params\",\"frequencyPenalty\": 1.5,\"presencePenalty\": 1.5,\"stop\": \"<|im_end|>\",\"temperature\": 0,\"topP\": 1},\"model\":\"azure__openai__gpt_4o_mini\",\"numTokensForCompletion\":8400,\"promptTemplate\":\"It is , consider these travel options and answer the.\",\"systemMessage\":\"You are a helpful travel assistant specialized in budget travel\"}}',\n\t\t\t\t'--token=test',\n\t\t\t])\n\n\t\t\t.it(\n\t\t\t\t'should send the correct request and output the response (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlFixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('ai:extract with ai agent', function () {\n\t\tconst expectedRequestBody = {\n\t\t\tprompt: 'firstName, lastName, location, yearOfBirth, company',\n\t\t\titems: [\n\t\t\t\t{\n\t\t\t\t\tid: '12345',\n\t\t\t\t\ttype: 'file',\n\t\t\t\t\tcontent: 'one,two,three',\n\t\t\t\t},\n\t\t\t],\n\t\t\tai_agent: getAgentInRequestBody('ai_agent_extract'),\n\t\t};\n\t\tconst expectedResponseBody = {\n\t\t\tanswer: '{\"firstName\": \"John\", \"lastName\": \"Doe\", \"location\": \"San Francisco\", \"yearOfBirth\": \"1990\", \"company\": \"Box\"}',\n\t\t\tcreated_at: '2025-05-02T14:51:30.567Z',\n\t\t\tcompletion_reason: 'done',\n\t\t\tai_agent_info: {\n\t\t\t\tmodels: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'google__gemini_2_0_flash_001',\n\t\t\t\t\t\tprovider: 'google',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tprocessor: 'basic_text',\n\t\t\t},\n\t\t};\n\n\t\tconst fixture = getFixture('ai/post_ai_extract_response');\n\t\tconst yamlFixture = getFixture('ai/post_ai_extract_response_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) => {\n\t\t\tapi.post('/2.0/ai/extract', expectedRequestBody).reply(\n\t\t\t\t200,\n\t\t\t\texpectedResponseBody\n\t\t\t);\n\t\t})\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:extract',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--prompt',\n\t\t\t\t'firstName, lastName, location, yearOfBirth, company',\n\t\t\t\t'--ai-agent',\n\t\t\t\t'{\"type\":\"ai_agent_extract\",\"basicText\":{\"llmEndpointParams\":{\"type\":\"openai_params\",\"frequencyPenalty\": 1.5,\"presencePenalty\": 1.5,\"stop\": \"<|im_end|>\",\"temperature\": 0,\"topP\": 1},\"model\": \"azure__openai__gpt_4o_mini\",\"numTokensForCompletion\": 8400,\"promptTemplate\": \"It is, consider these travel options and answer the.\",\"systemMessage\": \"You are a helpful travel assistant specialized in budget travel\"},\"longText\":{\"embeddings\":{ \"model\": \"azure__openai__text_embedding_ada_002\",\"strategy\":{\"id\": \"basic\",\"numTokensPerChunk\": 64}},\"llmEndpointParams\":{\"type\":\"openai_params\",\"frequencyPenalty\": 1.5,\"presencePenalty\": 1.5,\"stop\": \"<|im_end|>\",\"temperature\": 0,\"topP\": 1},\"model\":\"azure__openai__gpt_4o_mini\",\"numTokensForCompletion\":8400,\"promptTemplate\":\"It is , consider these travel options and answer the.\",\"systemMessage\":\"You are a helpful travel assistant specialized in budget travel\"}}',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\n\t\t\t.it(\n\t\t\t\t'should send the correct request and output the response (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) => {\n\t\t\tapi.post('/2.0/ai/extract', expectedRequestBody).reply(\n\t\t\t\t200,\n\t\t\t\texpectedResponseBody\n\t\t\t);\n\t\t})\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:extract',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--prompt',\n\t\t\t\t'firstName, lastName, location, yearOfBirth, company',\n\t\t\t\t'--ai-agent',\n\t\t\t\t'{\"type\":\"ai_agent_extract\",\"basicText\":{\"llmEndpointParams\":{\"type\":\"openai_params\",\"frequencyPenalty\": 1.5,\"presencePenalty\": 1.5,\"stop\": \"<|im_end|>\",\"temperature\": 0,\"topP\": 1},\"model\": \"azure__openai__gpt_4o_mini\",\"numTokensForCompletion\": 8400,\"promptTemplate\": \"It is, consider these travel options and answer the.\",\"systemMessage\": \"You are a helpful travel assistant specialized in budget travel\"},\"longText\":{\"embeddings\":{ \"model\": \"azure__openai__text_embedding_ada_002\",\"strategy\":{\"id\": \"basic\",\"numTokensPerChunk\": 64}},\"llmEndpointParams\":{\"type\":\"openai_params\",\"frequencyPenalty\": 1.5,\"presencePenalty\": 1.5,\"stop\": \"<|im_end|>\",\"temperature\": 0,\"topP\": 1},\"model\":\"azure__openai__gpt_4o_mini\",\"numTokensForCompletion\":8400,\"promptTemplate\":\"It is , consider these travel options and answer the.\",\"systemMessage\":\"You are a helpful travel assistant specialized in budget travel\"}}',\n\t\t\t\t'--token=test',\n\t\t\t])\n\n\t\t\t.it(\n\t\t\t\t'should send the correct request and output the response (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlFixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('ai:extract-structured with metadata template', function () {\n\t\tconst expectedRequestBody = {\n\t\t\titems: [\n\t\t\t\t{\n\t\t\t\t\tid: '12345',\n\t\t\t\t\ttype: 'file',\n\t\t\t\t\tcontent: 'one,two,three',\n\t\t\t\t},\n\t\t\t],\n\t\t\tmetadata_template: {\n\t\t\t\ttype: 'metadata_template',\n\t\t\t\tscope: 'enterprise',\n\t\t\t\ttemplate_key: 'test',\n\t\t\t},\n\t\t};\n\t\tconst expectedResponseBody = {\n\t\t\tanswer: {\n\t\t\t\tfirstName: 'John',\n\t\t\t\tlastName: 'Doe',\n\t\t\t},\n\t\t\tcreated_at: '2025-04-29T07:25:24.366-07:00',\n\t\t\tcompletion_reason: 'done',\n\t\t\tai_agent_info: {\n\t\t\t\tmodels: [\n\t\t\t\t\t{\n\t\t\t\t\t\tname: 'google__gemini_2_0_flash_001',\n\t\t\t\t\t\tprovider: 'google',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tprocessor: 'basic_text',\n\t\t\t},\n\t\t};\n\n\t\tconst fixture = getFixture('ai/post_ai_extract_structured_response');\n\t\tconst yamlFixture = getFixture(\n\t\t\t'ai/post_ai_extract_structured_response_yaml.txt'\n\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) => {\n\t\t\tapi.post('/2.0/ai/extract_structured', expectedRequestBody).reply(\n\t\t\t\t200,\n\t\t\t\texpectedResponseBody\n\t\t\t);\n\t\t})\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:extract-structured',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--metadata-template=type=metadata_template,scope=enterprise,template_key=test',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\n\t\t\t.it(\n\t\t\t\t'should send the correct request and output the response (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) => {\n\t\t\tapi.post('/2.0/ai/extract_structured', expectedRequestBody).reply(\n\t\t\t\t200,\n\t\t\t\texpectedResponseBody\n\t\t\t);\n\t\t})\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'ai:extract-structured',\n\t\t\t\t'--items=content=one,two,three,id=12345,type=file',\n\t\t\t\t'--metadata-template=type=metadata_template,scope=enterprise,template_key=test',\n\t\t\t\t'--token=test',\n\t\t\t])\n\n\t\t\t.it(\n\t\t\t\t'should send the correct request and output the response (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlFixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/bulk.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst { assert } = require('chai');\nconst fs = require('fs-extra');\nconst path = require('node:path');\nconst {\n\tgetFixture,\n\tTEST_API_ROOT,\n\tgetBulkProgressBar,\n} = require('../helpers/test-helper');\nconst os = require('node:os');\nconst debug = require('debug');\n\ndescribe('Bulk', function () {\n\tlet boxItemId = '33333',\n\t\tlogin = 'steve.jobs@example.com',\n\t\taddCollaborationFixture1 = getFixture(\n\t\t\t'bulk/post_collaborations_user_1'\n\t\t),\n\t\taddCollaborationFixture2 = getFixture(\n\t\t\t'bulk/post_collaborations_user_2'\n\t\t),\n\t\taddCollaborationFixture3 = getFixture(\n\t\t\t'bulk/post_collaborations_user_3'\n\t\t),\n\t\tjsonOutput = getFixture('output/bulk_output_json.txt');\n\n\tdescribe('CSV Input', function () {\n\t\tlet inputFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'..',\n\t\t\t\t'fixtures/bulk/input.csv'\n\t\t\t),\n\t\t\tsaveFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'..',\n\t\t\t\t'fixtures/bulk/saveTest.txt'\n\t\t\t),\n\t\t\tcsvOutput = getFixture('bulk/post_collaborations_csv.csv'),\n\t\t\tmultipleFlagValuesInputFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'../fixtures/bulk/input_multiple_same_flag.csv'\n\t\t\t),\n\t\t\temptyStringInputFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'../fixtures/bulk/input_with_empty_string.csv'\n\t\t\t),\n\t\t\tmetadataUpdateInputFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'../fixtures/bulk/input_metadata_update.csv'\n\t\t\t),\n\t\t\tsignRequestCreateInputFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'../fixtures/bulk/input_sign_request_create.csv'\n\t\t\t),\n\t\t\ttableOutput = getFixture('bulk/post_collaborations_table.txt'),\n\t\t\tcreateSignRequestFixture = getFixture('bulk/post_sign_requests');\n\n\t\tlet addCollaborationBody1 = {\n\t\t\titem: {\n\t\t\t\ttype: 'folder',\n\t\t\t\tid: '11111',\n\t\t\t},\n\t\t\taccessible_by: {\n\t\t\t\ttype: 'user',\n\t\t\t\tlogin,\n\t\t\t},\n\t\t\trole: 'previewer',\n\t\t\tcan_view_path: true,\n\t\t};\n\t\tlet addCollaborationBody2 = {\n\t\t\titem: {\n\t\t\t\ttype: 'folder',\n\t\t\t\tid: '22222',\n\t\t\t},\n\t\t\taccessible_by: {\n\t\t\t\ttype: 'user',\n\t\t\t\tlogin: 'roger.federer@example.com',\n\t\t\t},\n\t\t\trole: 'previewer',\n\t\t\tcan_view_path: true,\n\t\t};\n\t\tlet addCollaborationBody3 = {\n\t\t\titem: {\n\t\t\t\ttype: 'file',\n\t\t\t\tid: '33333',\n\t\t\t},\n\t\t\taccessible_by: {\n\t\t\t\ttype: 'user',\n\t\t\t\tlogin: 'dominic.toretto@example.com',\n\t\t\t},\n\t\t\trole: 'previewer',\n\t\t\tcan_view_path: false,\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody2)\n\t\t\t\t.reply(200, addCollaborationFixture2)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody3)\n\t\t\t\t.reply(200, addCollaborationFixture3)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\tboxItemId,\n\t\t\t\t'--can-view-path',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t'--previewer',\n\t\t\t\t`--bulk-file-path=${inputFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create multiple collaborations for multiple Box items with can-view-path and login flags passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\tlet expectedMessage = getBulkProgressBar(3);\n\t\t\t\t\texpectedMessage += `All bulk input entries processed successfully.${os.EOL}`;\n\t\t\t\t\tassert.equal(context.stderr, expectedMessage);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody2)\n\t\t\t\t.reply(200, addCollaborationFixture2)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody3)\n\t\t\t\t.reply(200, addCollaborationFixture3)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\tboxItemId,\n\t\t\t\t'--can-view-path',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t'--previewer',\n\t\t\t\t`--bulk-file-path=${inputFilePath}`,\n\t\t\t\t'--csv',\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create multiple collaborations for multiple Box items with can-view-path and login flags passed (CSV Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, csvOutput);\n\t\t\t\t\tlet expectedMessage = getBulkProgressBar(3);\n\t\t\t\t\texpectedMessage += `All bulk input entries processed successfully.${os.EOL}`;\n\t\t\t\t\tassert.equal(context.stderr, expectedMessage);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody2)\n\t\t\t\t.reply(200, addCollaborationFixture2)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody3)\n\t\t\t\t.reply(200, addCollaborationFixture3)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\tboxItemId,\n\t\t\t\t'--can-view-path',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t'--previewer',\n\t\t\t\t`--bulk-file-path=${inputFilePath}`,\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create multiple collaborations for multiple Box items with can-view-path and login flags passed (Table Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, tableOutput);\n\t\t\t\t\tlet expectedMessage = getBulkProgressBar(3);\n\t\t\t\t\texpectedMessage += `All bulk input entries processed successfully.${os.EOL}`;\n\t\t\t\t\tassert.equal(context.stderr, expectedMessage);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody2)\n\t\t\t\t.reply(200, addCollaborationFixture2)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody3)\n\t\t\t\t.reply(200, addCollaborationFixture3)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\tboxItemId,\n\t\t\t\t'--can-view-path',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t'--previewer',\n\t\t\t\t`--bulk-file-path=${inputFilePath}`,\n\t\t\t\t`--save-to-file-path=${saveFilePath}`,\n\t\t\t\t'-y',\n\t\t\t\t'--json',\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create multiple collaborations for multiple Box items with can-view-path and login flags passed (Save JSON Output To File)',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet savedFileContents = fs.readFileSync(\n\t\t\t\t\t\tsaveFilePath,\n\t\t\t\t\t\t'utf8'\n\t\t\t\t\t);\n\n\t\t\t\t\tassert.equal(savedFileContents, jsonOutput);\n\n\t\t\t\t\tlet expectedMessage = getBulkProgressBar(3);\n\t\t\t\t\texpectedMessage += `Output written to ${saveFilePath}${os.EOL}`;\n\t\t\t\t\texpectedMessage += `All bulk input entries processed successfully.${os.EOL}`;\n\t\t\t\t\tassert.equal(context.stderr, expectedMessage);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody2)\n\t\t\t\t.reply(200, addCollaborationFixture2)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody3)\n\t\t\t\t.reply(200, addCollaborationFixture3)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\tboxItemId,\n\t\t\t\t'--previewer',\n\t\t\t\t'--can-view-path',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t`--bulk-file-path=${path.join(__dirname, '../fixtures/bulk/input_key_casing.csv')}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should permit keys that do not use flag punctuation');\n\n\t\tlet folderLockBody = {\n\t\t\tfolder: {\n\t\t\t\ttype: 'folder',\n\t\t\t\tid: '1243215',\n\t\t\t},\n\t\t};\n\t\tlet folderLockBodyString = JSON.stringify(folderLockBody);\n\t\tlet folderLockInputFilePath = path.join(\n\t\t\t__dirname,\n\t\t\t'../fixtures/bulk/input_manual_request_folder_lock.csv'\n\t\t);\n\t\tlet folderLockBodyFixture = getFixture('bulk/post_folders_lock.json');\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.matchHeader('Content-Type', 'application/json;version=1')\n\t\t\t\t.matchHeader('Accept', 'application/json;version=1')\n\t\t\t\t.post('/2.0/folder_locks', folderLockBody)\n\t\t\t\t.reply(200, folderLockBodyFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'request',\n\t\t\t\t`--body=${folderLockBodyString}`,\n\t\t\t\t'--header=Content-Type: application/json;version=1',\n\t\t\t\t'--header=Accept: application/json;version=1',\n\t\t\t\t`--bulk-file-path=${folderLockInputFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should allow flags that can be specified multiple times in a single command to be passed through the command line for bulk commands'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/search')\n\t\t\t\t.query({\n\t\t\t\t\tmdfilters:\n\t\t\t\t\t\t'[{\"scope\":\"enterprise\",\"templateKey\":\"myTemplate\",\"filters\":{\"name\":\"Matt\",\"age\":{\"lt\":30,\"gt\":30}}}]',\n\t\t\t\t\tlimit: 100,\n\t\t\t\t\tquery: '',\n\t\t\t\t})\n\t\t\t\t.reply(200, { entries: [] })\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'search',\n\t\t\t\t`--bulk-file-path=${multipleFlagValuesInputFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should process number-postfixed columns as multiple uses of same flag',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, `[]${os.EOL}`);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put('/2.0/files/1234/metadata/enterprise/testTemplate', [\n\t\t\t\t\t{\n\t\t\t\t\t\top: 'add',\n\t\t\t\t\t\tpath: '/foo',\n\t\t\t\t\t\tvalue: 'bar',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\top: 'test',\n\t\t\t\t\t\tpath: '/baz',\n\t\t\t\t\t\tvalue: ['stuff', 'nonsense'],\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\top: 'add',\n\t\t\t\t\t\tpath: '/anotherOne',\n\t\t\t\t\t\tvalue: -2.5,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\top: 'copy',\n\t\t\t\t\t\tfrom: '/sou~1rce/0',\n\t\t\t\t\t\tpath: '/destination',\n\t\t\t\t\t},\n\t\t\t\t])\n\t\t\t\t.reply(200, {})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:metadata:update',\n\t\t\t\t'1234',\n\t\t\t\t'--template-key=testTemplate',\n\t\t\t\t`--bulk-file-path=${metadataUpdateInputFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should preserve the absolute order of columns in command arguments'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put('/2.0/files/11111', {\n\t\t\t\t\tname: 'dat.dat',\n\t\t\t\t})\n\t\t\t\t.reply(200, {\n\t\t\t\t\ttype: 'file',\n\t\t\t\t\tid: '11111',\n\t\t\t\t\tname: 'dat.dat',\n\t\t\t\t\tdescription: 'Still here!',\n\t\t\t\t})\n\t\t\t\t.put('/2.0/files/22222', {\n\t\t\t\t\tname: 'doc.docx',\n\t\t\t\t\tdescription: '',\n\t\t\t\t})\n\t\t\t\t.reply(200, {\n\t\t\t\t\ttype: 'file',\n\t\t\t\t\tid: '22222',\n\t\t\t\t\tname: 'doc.docx',\n\t\t\t\t\tdescription: '',\n\t\t\t\t})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:rename',\n\t\t\t\t`--bulk-file-path=${emptyStringInputFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should correctly parse empty field and empty string value');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t'--previewer',\n\t\t\t\t`--bulk-file-path=${path.join(__dirname, '../fixtures/bulk/input_bogus_keys.csv')}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should ignore CSV keys that do not map to valid args or flags'\n\t\t\t);\n\n\t\tlet folderCollabInput = path.join(\n\t\t\t__dirname,\n\t\t\t'..',\n\t\t\t'fixtures/bulk/folder_collab_input.csv'\n\t\t);\n\t\tlet fakeCollab1 = {\n\t\t\ttype: 'collaboration',\n\t\t\tid: '12345',\n\t\t};\n\t\tlet fakeCollab2 = {\n\t\t\ttype: 'collaboration',\n\t\t\tid: '54321',\n\t\t};\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', {\n\t\t\t\t\titem: {\n\t\t\t\t\t\ttype: 'folder',\n\t\t\t\t\t\tid: '11111',\n\t\t\t\t\t},\n\t\t\t\t\taccessible_by: {\n\t\t\t\t\t\ttype: 'user',\n\t\t\t\t\t\tlogin: 'mario@example.com',\n\t\t\t\t\t},\n\t\t\t\t\trole: 'viewer',\n\t\t\t\t})\n\t\t\t\t.query({ fields: 'id' })\n\t\t\t\t.reply(200, fakeCollab1)\n\t\t\t\t.post('/2.0/collaborations', {\n\t\t\t\t\titem: {\n\t\t\t\t\t\ttype: 'folder',\n\t\t\t\t\t\tid: '22222',\n\t\t\t\t\t},\n\t\t\t\t\taccessible_by: {\n\t\t\t\t\t\ttype: 'user',\n\t\t\t\t\t\tlogin: 'wario@example.com',\n\t\t\t\t\t},\n\t\t\t\t\trole: 'viewer',\n\t\t\t\t})\n\t\t\t\t.query({ fields: 'id' })\n\t\t\t\t.reply(409, {\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\tstatus: 409,\n\t\t\t\t\tcode: 'collaboration_already_exists',\n\t\t\t\t\tcontext_info: {\n\t\t\t\t\t\tconflicts: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'collaboration',\n\t\t\t\t\t\t\t\tid: '871642494',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\thelp_url: 'http://developers.box.com/docs/#errors',\n\t\t\t\t\tmessage: '',\n\t\t\t\t\trequest_id: '170397861659135cc65a65',\n\t\t\t\t})\n\t\t\t\t.post('/2.0/collaborations', {\n\t\t\t\t\titem: {\n\t\t\t\t\t\ttype: 'folder',\n\t\t\t\t\t\tid: '33333',\n\t\t\t\t\t},\n\t\t\t\t\taccessible_by: {\n\t\t\t\t\t\ttype: 'user',\n\t\t\t\t\t\tlogin: 'peach@example.com',\n\t\t\t\t\t},\n\t\t\t\t\trole: 'viewer',\n\t\t\t\t})\n\t\t\t\t.query({ fields: 'id' })\n\t\t\t\t.reply(200, fakeCollab2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:collaborations:add',\n\t\t\t\t'--viewer',\n\t\t\t\t`--bulk-file-path=${folderCollabInput}`,\n\t\t\t\t'--json',\n\t\t\t\t'--fields=id',\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should catch and report errors in subcommands without stopping bulk execution',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedOutput = JSON.stringify(\n\t\t\t\t\t\t[fakeCollab1, fakeCollab2],\n\t\t\t\t\t\tnull,\n\t\t\t\t\t\t4\n\t\t\t\t\t);\n\n\t\t\t\t\tlet expectedErrorOutput = getBulkProgressBar(3);\n\t\t\t\t\texpectedErrorOutput += `1 entry failed!${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `----------${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `Entry 2 (${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `    id=22222${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `    login=wario@example.com${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `) failed with error:${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `Unexpected API Response [409 Conflict | 170397861659135cc65a65] collaboration_already_exists${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `Conflicts:${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `    -${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `        Type: collaboration${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `        ID: '871642494'${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += os.EOL;\n\n\t\t\t\t\tassert.equal(context.stdout, expectedOutput + os.EOL);\n\t\t\t\t\tassert.equal(context.stderr, expectedErrorOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:collaborations:add',\n\t\t\t\t'12345',\n\t\t\t\t`--bulk-file-path=${path.join(__dirname, '..', 'fixtures/bulk/folder_collab_input_no_header.csv')}`,\n\t\t\t\t'--json',\n\t\t\t\t'--fields=id',\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should report errors on missing headers', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`CSV input file should contain the headers row and at least on data row${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\n\t\ttest.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:collaborations:add',\n\t\t\t\t'12345',\n\t\t\t\t`--bulk-file-path=${path.join(__dirname, '..', 'fixtures/bulk/folder_collab_input_no_header_multiple.csv')}`,\n\t\t\t\t'--json',\n\t\t\t\t'--fields=id',\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should report errors on missing headers if specified multiple rows',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedErrorOutput = getBulkProgressBar(2);\n\t\t\t\t\texpectedErrorOutput += `2 entries failed!${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `----------${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `Entry 1 (${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += os.EOL;\n\t\t\t\t\texpectedErrorOutput += `) failed with error:${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `Missing required flag for collaboration role${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += os.EOL;\n\t\t\t\t\texpectedErrorOutput += `----------${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `Entry 2 (${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += os.EOL;\n\t\t\t\t\texpectedErrorOutput += `) failed with error:${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `Missing required flag for collaboration role${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += os.EOL;\n\n\t\t\t\t\tassert.equal(context.stderr, expectedErrorOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.matchHeader('As-User', '12345')\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t'--previewer',\n\t\t\t\t`--bulk-file-path=${path.join(__dirname, '../fixtures/bulk/input_asuser_flag_single.csv')}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should map As-User header from the bulk file');\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.matchHeader('As-User', '12345')\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.matchHeader('As-User', '')\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t'--previewer',\n\t\t\t\t`--bulk-file-path=${path.join(__dirname, '../fixtures/bulk/input_asuser_flag_multiple.csv')}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send empty As-User header when not present in the bulk file'\n\t\t\t);\n\n\t\tconst terminateSessionFixture = getFixture(\n\t\t\t'bulk/post_terminate_sessions'\n\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/users/terminate_sessions', {\n\t\t\t\t\tuser_logins: ['user1@example.com'],\n\t\t\t\t\tuser_ids: ['111'],\n\t\t\t\t})\n\t\t\t\t.reply(201, terminateSessionFixture)\n\t\t\t\t.post('/2.0/users/terminate_sessions', {\n\t\t\t\t\tuser_logins: ['user2@example.com'],\n\t\t\t\t\tuser_ids: ['222'],\n\t\t\t\t})\n\t\t\t\t.reply(201, terminateSessionFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'users:terminate-session',\n\t\t\t\t`--bulk-file-path=${path.join(__dirname, '../fixtures/bulk/input_users_terminate_sessions.csv')}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send terminate sessions request with user ids and logins',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedOutput = [\n\t\t\t\t\t\tJSON.parse(terminateSessionFixture),\n\t\t\t\t\t\tJSON.parse(terminateSessionFixture),\n\t\t\t\t\t];\n\t\t\t\t\tassert.deepEqual(\n\t\t\t\t\t\tJSON.parse(context.stdout),\n\t\t\t\t\t\texpectedOutput\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/groups/terminate_sessions', {\n\t\t\t\t\tgroup_ids: ['111'],\n\t\t\t\t})\n\t\t\t\t.reply(201, terminateSessionFixture)\n\t\t\t\t.post('/2.0/groups/terminate_sessions', {\n\t\t\t\t\tgroup_ids: ['222'],\n\t\t\t\t})\n\t\t\t\t.reply(201, terminateSessionFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'groups:terminate-session',\n\t\t\t\t`--bulk-file-path=${path.join(__dirname, '../fixtures/bulk/input_groups_terminate_sessions.csv')}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send terminate sessions request with groups ids',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedOutput = [\n\t\t\t\t\t\tJSON.parse(terminateSessionFixture),\n\t\t\t\t\t\tJSON.parse(terminateSessionFixture),\n\t\t\t\t\t];\n\t\t\t\t\tassert.deepEqual(\n\t\t\t\t\t\tJSON.parse(context.stdout),\n\t\t\t\t\t\texpectedOutput\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/sign_requests').reply(200, createSignRequestFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'sign-requests:create',\n\t\t\t\t`--bulk-file-path=${signRequestCreateInputFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should correctly process commands that do not contain argument parameters',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedOutput = [];\n\t\t\t\t\texpectedOutput.push(JSON.parse(createSignRequestFixture));\n\t\t\t\t\tassert.deepEqual(\n\t\t\t\t\t\tJSON.parse(context.stdout),\n\t\t\t\t\t\texpectedOutput\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('JSON Input', function () {\n\t\tlet entriesInputFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'../fixtures/bulk/input_entries.json'\n\t\t\t),\n\t\t\tbareArrayInputFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'../fixtures/bulk/input_array.json'\n\t\t\t),\n\t\t\tsingleObjectInputFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'../fixtures/bulk/input_object.json'\n\t\t\t),\n\t\t\twrongExtensionInputFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'../fixtures/bulk/input.txt'\n\t\t\t),\n\t\t\tinvalidInputFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'../fixtures/bulk/input_invalid.json'\n\t\t\t),\n\t\t\tmultipleFlagValuesInputFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'../fixtures/bulk/input_multiple_same_flag.json'\n\t\t\t),\n\t\t\tmetadataUpdateInputFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'../fixtures/bulk/input_metadata_update.json'\n\t\t\t),\n\t\t\tsaveFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'..',\n\t\t\t\t'fixtures/bulk/saveTest.txt'\n\t\t\t);\n\n\t\tlet addCollaborationBody1 = {\n\t\t\titem: {\n\t\t\t\ttype: 'folder',\n\t\t\t\tid: '11111',\n\t\t\t},\n\t\t\taccessible_by: {\n\t\t\t\ttype: 'user',\n\t\t\t\tlogin,\n\t\t\t},\n\t\t\trole: 'previewer',\n\t\t\tcan_view_path: true,\n\t\t};\n\t\tlet addCollaborationBody2 = {\n\t\t\titem: {\n\t\t\t\ttype: 'folder',\n\t\t\t\tid: '22222',\n\t\t\t},\n\t\t\taccessible_by: {\n\t\t\t\ttype: 'user',\n\t\t\t\tlogin: 'roger.federer@example.com',\n\t\t\t},\n\t\t\trole: 'previewer',\n\t\t\tcan_view_path: true,\n\t\t};\n\t\tlet addCollaborationBody3 = {\n\t\t\titem: {\n\t\t\t\ttype: 'file',\n\t\t\t\tid: '33333',\n\t\t\t},\n\t\t\taccessible_by: {\n\t\t\t\ttype: 'user',\n\t\t\t\tlogin: 'dominic.toretto@example.com',\n\t\t\t},\n\t\t\trole: 'previewer',\n\t\t\tcan_view_path: false,\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody2)\n\t\t\t\t.reply(200, addCollaborationFixture2)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody3)\n\t\t\t\t.reply(200, addCollaborationFixture3)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\tboxItemId,\n\t\t\t\t'--can-view-path',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t'--previewer',\n\t\t\t\t`--bulk-file-path=${entriesInputFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should process multiple inputs from JSON file with entries property (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\tlet expectedErrorOutput = getBulkProgressBar(3);\n\t\t\t\t\texpectedErrorOutput += `All bulk input entries processed successfully.${os.EOL}`;\n\t\t\t\t\tassert.equal(context.stderr, expectedErrorOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody2)\n\t\t\t\t.reply(200, addCollaborationFixture2)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody3)\n\t\t\t\t.reply(200, addCollaborationFixture3)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\tboxItemId,\n\t\t\t\t'--can-view-path',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t'--previewer',\n\t\t\t\t`--bulk-file-path=${bareArrayInputFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should process multiple inputs from JSON file with top-level array',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\tlet expectedErrorOutput = getBulkProgressBar(3);\n\t\t\t\t\texpectedErrorOutput += `All bulk input entries processed successfully.${os.EOL}`;\n\t\t\t\t\tassert.equal(context.stderr, expectedErrorOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\tboxItemId,\n\t\t\t\t'--can-view-path',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t`--bulk-file-path=${singleObjectInputFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should output error when input file does not contain inputs array',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Expected input file to contain an array of input objects, but none found${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\tboxItemId,\n\t\t\t\t'--can-view-path',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t`--bulk-file-path=${wrongExtensionInputFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should output error when input file does not have appropriate extension',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Input file had extension \".txt\", but only .json and .csv are supported${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\tboxItemId,\n\t\t\t\t'--can-view-path',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t`--bulk-file-path=${invalidInputFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should output CLI error message when input file is not valid JSON',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Could not parse JSON input file ${invalidInputFilePath}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\tboxItemId,\n\t\t\t\t'--can-view-path',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t`--bulk-file-path=${invalidInputFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--verbose',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should output wrapped error when input file is not valid JSON and verbose flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tdebug.disable();\n\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`BoxCLIError: Could not parse JSON input file ${invalidInputFilePath}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t\tassert.include(context.stderr, 'Caused by: SyntaxError: ');\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody2)\n\t\t\t\t.reply(200, addCollaborationFixture2)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody3)\n\t\t\t\t.reply(200, addCollaborationFixture3)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\tboxItemId,\n\t\t\t\t'--can-view-path',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t'--previewer',\n\t\t\t\t`--bulk-file-path=${entriesInputFilePath}`,\n\t\t\t\t`--save-to-file-path=${saveFilePath}`,\n\t\t\t\t'-y',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should process multiple inputs from JSON file with entries property (Save JSON Output To File)',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet savedFileContents = fs.readFileSync(\n\t\t\t\t\t\tsaveFilePath,\n\t\t\t\t\t\t'utf8'\n\t\t\t\t\t);\n\n\t\t\t\t\tassert.equal(savedFileContents, jsonOutput);\n\n\t\t\t\t\tlet expectedMessage = getBulkProgressBar(3);\n\t\t\t\t\texpectedMessage += `Output written to ${saveFilePath}${os.EOL}`;\n\t\t\t\t\texpectedMessage += `All bulk input entries processed successfully.${os.EOL}`;\n\t\t\t\t\tassert.equal(context.stderr, expectedMessage);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody2)\n\t\t\t\t.reply(200, addCollaborationFixture2)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody3)\n\t\t\t\t.reply(200, addCollaborationFixture3)\n\t\t)\n\t\t\t.do(() => {\n\t\t\t\tfs.writeFileSync(saveFilePath, 'foo', 'utf8');\n\t\t\t})\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.stdin(`y${os.EOL}`, 500)\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\tboxItemId,\n\t\t\t\t'--can-view-path',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t'--previewer',\n\t\t\t\t`--bulk-file-path=${entriesInputFilePath}`,\n\t\t\t\t`--save-to-file-path=${saveFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should prompt when overwriting existing file', (context) => {\n\t\t\t\tlet savedFileContents = fs.readFileSync(saveFilePath, 'utf8');\n\n\t\t\t\tassert.equal(savedFileContents, jsonOutput);\n\t\t\t\tassert.include(context.stdout, '(y/N) y');\n\n\t\t\t\tlet expectedMessage = getBulkProgressBar(3);\n\t\t\t\texpectedMessage += `Output written to ${saveFilePath}${os.EOL}`;\n\t\t\t\texpectedMessage += `All bulk input entries processed successfully.${os.EOL}`;\n\t\t\t\tassert.equal(context.stderr, expectedMessage);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody2)\n\t\t\t\t.reply(200, addCollaborationFixture2)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody3)\n\t\t\t\t.reply(200, addCollaborationFixture3)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:create',\n\t\t\t\tboxItemId,\n\t\t\t\t'--can-view-path',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t'--previewer',\n\t\t\t\t`--bulk-file-path=${entriesInputFilePath}`,\n\t\t\t\t`--save-to-file-path=${path.dirname(saveFilePath)}`,\n\t\t\t\t'-y',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should write file with default name when save path is a directory',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet outputMessage = context.stderr;\n\t\t\t\t\tlet expectedFilenameRegex =\n\t\t\t\t\t\t/collaborations-create-\\d{4}-\\d{2}-\\d{2}_\\d{2}_\\d{2}_\\d{2}_\\d{3}\\.json/u;\n\t\t\t\t\tassert.match(outputMessage, expectedFilenameRegex);\n\t\t\t\t\tlet outputFilename = outputMessage.match(\n\t\t\t\t\t\texpectedFilenameRegex\n\t\t\t\t\t)[0];\n\t\t\t\t\tlet filePath = path.join(\n\t\t\t\t\t\tpath.dirname(saveFilePath),\n\t\t\t\t\t\toutputFilename\n\t\t\t\t\t);\n\n\t\t\t\t\tlet savedFileContents = fs.readFileSync(filePath, 'utf8');\n\t\t\t\t\tfs.unlinkSync(filePath);\n\n\t\t\t\t\tassert.equal(savedFileContents, jsonOutput);\n\n\t\t\t\t\tlet expectedMessage = getBulkProgressBar(3);\n\t\t\t\t\texpectedMessage += `Output written to ${filePath}${os.EOL}`;\n\t\t\t\t\texpectedMessage += `All bulk input entries processed successfully.${os.EOL}`;\n\t\t\t\t\tassert.equal(context.stderr, expectedMessage);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody2)\n\t\t\t\t.reply(200, addCollaborationFixture2)\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody3)\n\t\t\t\t.reply(200, addCollaborationFixture3)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\tboxItemId,\n\t\t\t\t'--can-view-path',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t'--previewer',\n\t\t\t\t`--bulk-file-path=${path.join(__dirname, '../fixtures/bulk/input_key_casing.json')}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should permit keys that do not use flag punctuation');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/search')\n\t\t\t\t.query({\n\t\t\t\t\tmdfilters:\n\t\t\t\t\t\t'[{\"scope\":\"enterprise\",\"templateKey\":\"myTemplate\",\"filters\":{\"name\":\"Matt\",\"age\":{\"lt\":30,\"gt\":30}}}]',\n\t\t\t\t\tlimit: 100,\n\t\t\t\t\tquery: '',\n\t\t\t\t})\n\t\t\t\t.reply(200, { entries: [] })\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'search',\n\t\t\t\t`--bulk-file-path=${multipleFlagValuesInputFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should process array as multiple uses of same flag',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, `[]${os.EOL}`);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put('/2.0/files/1234/metadata/enterprise/testTemplate', [\n\t\t\t\t\t{\n\t\t\t\t\t\top: 'add',\n\t\t\t\t\t\tpath: '/foo',\n\t\t\t\t\t\tvalue: 'bar',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\top: 'test',\n\t\t\t\t\t\tpath: '/baz',\n\t\t\t\t\t\tvalue: ['stuff', 'nonsense'],\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\top: 'add',\n\t\t\t\t\t\tpath: '/anotherOne',\n\t\t\t\t\t\tvalue: -2.5,\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\top: 'copy',\n\t\t\t\t\t\tfrom: '/sou~1rce/0',\n\t\t\t\t\t\tpath: '/destination',\n\t\t\t\t\t},\n\t\t\t\t])\n\t\t\t\t.reply(200, {})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:metadata:update',\n\t\t\t\t'1234',\n\t\t\t\t'--template-key=testTemplate',\n\t\t\t\t`--bulk-file-path=${metadataUpdateInputFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should preserve the absolute order of columns in command arguments'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t'--previewer',\n\t\t\t\t`--bulk-file-path=${path.join(__dirname, '../fixtures/bulk/input_nested_keys.json')}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should process nested keys into top-level args');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody1)\n\t\t\t\t.reply(200, addCollaborationFixture1)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaborations:add',\n\t\t\t\t`--login=${login}`,\n\t\t\t\t'--previewer',\n\t\t\t\t`--bulk-file-path=${path.join(__dirname, '../fixtures/bulk/input_bogus_keys.json')}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should ignore JSON keys that do not map to valid args or flags'\n\t\t\t);\n\t});\n\n\tdescribe('Output formatting', function () {\n\t\tlet inputFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'../fixtures/bulk/bulk_files_tasks_list_input.json'\n\t\t\t),\n\t\t\tfixture = getFixture('files/get_files_id_tasks_page_1'),\n\t\t\tfixture2 = getFixture('files/get_files_id_tasks_page_2'),\n\t\t\tfixture3 = getFixture('folders/get_folders_id_items'),\n\t\t\tjsonCollectionOutput = getFixture(\n\t\t\t\t'output/bulk_collection_output_json.txt'\n\t\t\t),\n\t\t\ttableCollectionOutput = getFixture(\n\t\t\t\t'output/bulk_collection_output_table.txt'\n\t\t\t),\n\t\t\tcsvCollectionOutput = getFixture(\n\t\t\t\t'output/bulk_collection_output_csv.txt'\n\t\t\t),\n\t\t\tcsvItemsOutput = getFixture('output/bulk_items_output_csv.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/files/123/tasks')\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/files/123/tasks')\n\t\t\t\t.query({\n\t\t\t\t\toffset: 1,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t\t\t.get('/2.0/files/456/tasks')\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/files/456/tasks')\n\t\t\t\t.query({\n\t\t\t\t\toffset: 1,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t\t\t.get('/2.0/files/789/tasks')\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/files/789/tasks')\n\t\t\t\t.query({\n\t\t\t\t\toffset: 1,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:tasks:list',\n\t\t\t\t`--bulk-file-path=${inputFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should flatten output objects array when each command run returns an array (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonCollectionOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/files/123/tasks')\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/files/123/tasks')\n\t\t\t\t.query({\n\t\t\t\t\toffset: 1,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t\t\t.get('/2.0/files/456/tasks')\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/files/456/tasks')\n\t\t\t\t.query({\n\t\t\t\t\toffset: 1,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t\t\t.get('/2.0/files/789/tasks')\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/files/789/tasks')\n\t\t\t\t.query({\n\t\t\t\t\toffset: 1,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:tasks:list',\n\t\t\t\t`--bulk-file-path=${inputFilePath}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should output flattened table when each command run returns an array (Table Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, tableCollectionOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/files/123/tasks')\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/files/123/tasks')\n\t\t\t\t.query({\n\t\t\t\t\toffset: 1,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t\t\t.get('/2.0/files/456/tasks')\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/files/456/tasks')\n\t\t\t\t.query({\n\t\t\t\t\toffset: 1,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t\t\t.get('/2.0/files/789/tasks')\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/files/789/tasks')\n\t\t\t\t.query({\n\t\t\t\t\toffset: 1,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:tasks:list',\n\t\t\t\t`--bulk-file-path=${inputFilePath}`,\n\t\t\t\t'--csv',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should output flattened CSV when each command run returns an array (CSV Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, csvCollectionOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/folders/0/items')\n\t\t\t\t.query({ usemarker: true, limit: 1000 })\n\t\t\t\t.reply(200, fixture3)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr({ print: true })\n\t\t\t.command(['folders:items', '0', '--csv', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should output flattened CSV with union of all fields present in each item when each command run returns an array (CSV Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, csvItemsOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/collaboration-allowlist.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\n\ndescribe('Collaboration-Allowlist', function () {\n\tdescribe('collaboration-allowlist:get', function () {\n\t\tlet allowlistEntryId = '11111',\n\t\t\tfixture = getFixture(\n\t\t\t\t'collaboration-allowlist/get_collaboration_whitelist_entries_id'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/collaboration_whitelist_get_yaml.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/collaboration_whitelist_entries/${allowlistEntryId}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collaboration-allowlist:get',\n\t\t\t\tallowlistEntryId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should output JSON when --json flag is passed', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/collaboration_whitelist_entries/${allowlistEntryId}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collaboration-allowlist:get',\n\t\t\t\tallowlistEntryId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get a collaboration allowlist entry (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/collaboration_whitelist_entries/${allowlistEntryId}`)\n\t\t\t\t.query({ fields: 'direction' })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collaboration-allowlist:get',\n\t\t\t\tallowlistEntryId,\n\t\t\t\t'--fields=direction',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('collaboration-allowlist:add', function () {\n\t\tlet domain = 'test.com',\n\t\t\tdirection = 'both',\n\t\t\tfixture = getFixture(\n\t\t\t\t'collaboration-allowlist/post_collaboration_whitelists'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/collaboration_whitelist_add_yaml.txt'\n\t\t\t);\n\n\t\tlet expectedBody = {\n\t\t\tdomain: 'test.com',\n\t\t\tdirection: 'both',\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaboration_whitelist_entries', expectedBody)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collaboration-allowlist:add',\n\t\t\t\tdomain,\n\t\t\t\t`--direction=${direction}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should add a collaboration allowlist entry (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaboration_whitelist_entries', expectedBody)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collaboration-allowlist:add',\n\t\t\t\tdomain,\n\t\t\t\t`--direction=${direction}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should add a collaboration allowlist entry (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('collaboration-allowlist:delete', function () {\n\t\tlet allowlistEntryId = '11111';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(\n\t\t\t\t\t`/2.0/collaboration_whitelist_entries/${allowlistEntryId}`\n\t\t\t\t)\n\t\t\t\t.reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaboration-allowlist:delete',\n\t\t\t\tallowlistEntryId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should delete a collaboration allowlist entry', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Deleted collaboration allowlist entry ${allowlistEntryId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tdescribe('collaboration-allowlist', function () {\n\t\tlet fixture = getFixture(\n\t\t\t\t'collaboration-allowlist/get_collaboration_whitelist_entries_page_1'\n\t\t\t),\n\t\t\tfixture2 = getFixture(\n\t\t\t\t'collaboration-allowlist/get_collaboration_whitelist_entries_page_2'\n\t\t\t),\n\t\t\tjsonOutput = getFixture(\n\t\t\t\t'output/collaboration_whitelist_list_json.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/collaboration_whitelist_entries')\n\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/collaboration_whitelist_entries')\n\t\t\t\t.query({\n\t\t\t\t\tmarker: 'ZEDFO9',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['collaboration-allowlist', '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should list collaboration allowlist entries (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/collaboration_whitelist_entries')\n\t\t\t\t.query({ fields: 'direction', limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/collaboration_whitelist_entries')\n\t\t\t\t.query({\n\t\t\t\t\tfields: 'direction',\n\t\t\t\t\tmarker: 'ZEDFO9',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collaboration-allowlist',\n\t\t\t\t'--fields=direction',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('collaboration-allowlist:exemptions:get', function () {\n\t\tlet exemptionId = '11111',\n\t\t\tfixture = getFixture(\n\t\t\t\t'collaboration-allowlist/get_collaboration_whitelist_exempt_targets_id'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/collaboration_whitelist_get_exemption_yaml.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(\n\t\t\t\t\t`/2.0/collaboration_whitelist_exempt_targets/${exemptionId}`\n\t\t\t\t)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collaboration-allowlist:exemptions:get',\n\t\t\t\texemptionId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get a collaboration allowlist exemption (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(\n\t\t\t\t\t`/2.0/collaboration_whitelist_exempt_targets/${exemptionId}`\n\t\t\t\t)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collaboration-allowlist:exemptions:get',\n\t\t\t\texemptionId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get a collaboration allowlist exemption (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(\n\t\t\t\t\t`/2.0/collaboration_whitelist_exempt_targets/${exemptionId}`\n\t\t\t\t)\n\t\t\t\t.query({ fields: 'id' })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collaboration-allowlist:exemptions:get',\n\t\t\t\texemptionId,\n\t\t\t\t'--fields=id',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send the fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('collaboration-allowlist:exemptions:create', function () {\n\t\tlet userId = '5678',\n\t\t\tfixture = getFixture(\n\t\t\t\t'collaboration-allowlist/post_collaboration_exempt_targets'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/collaboration_whitelist_create_exemption_yaml.txt'\n\t\t\t);\n\n\t\tlet expectedBody = {\n\t\t\tuser: {\n\t\t\t\tid: userId,\n\t\t\t\ttype: 'user',\n\t\t\t},\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(\n\t\t\t\t\t'/2.0/collaboration_whitelist_exempt_targets',\n\t\t\t\t\texpectedBody\n\t\t\t\t)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collaboration-allowlist:exemptions:create',\n\t\t\t\tuserId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a collaboration allowlist exemption (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(\n\t\t\t\t\t'/2.0/collaboration_whitelist_exempt_targets',\n\t\t\t\t\texpectedBody\n\t\t\t\t)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collaboration-allowlist:exemptions:create',\n\t\t\t\tuserId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a collaboration allowlist exemption (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('collaboration-allowlist:exemptions', function () {\n\t\tlet fixture = getFixture(\n\t\t\t\t'collaboration-allowlist/get_collaboration_whitelist_exempt_targets_page_1'\n\t\t\t),\n\t\t\tfixture2 = getFixture(\n\t\t\t\t'collaboration-allowlist/get_collaboration_whitelist_exempt_targets_page_2'\n\t\t\t),\n\t\t\tjsonOutput = getFixture(\n\t\t\t\t'output/collaboration_whitelist_list_exemptions_json.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/collaboration_whitelist_exempt_targets')\n\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/collaboration_whitelist_exempt_targets')\n\t\t\t\t.query({\n\t\t\t\t\tmarker: 'ZDEH786',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collaboration-allowlist:exemptions',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should list collaboration allowlist exemptions (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/collaboration_whitelist_exempt_targets')\n\t\t\t\t.query({ fields: 'id', limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/collaboration_whitelist_exempt_targets')\n\t\t\t\t.query({\n\t\t\t\t\tfields: 'id',\n\t\t\t\t\tmarker: 'ZDEH786',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collaboration-allowlist:exemptions',\n\t\t\t\t'--fields=id',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('collaboration-allowlist:exemptions:delete', function () {\n\t\tlet exemptionId = '11111';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(\n\t\t\t\t\t`/2.0/collaboration_whitelist_exempt_targets/${exemptionId}`\n\t\t\t\t)\n\t\t\t\t.reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collaboration-allowlist:exemptions:delete',\n\t\t\t\texemptionId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should delete collaboration allowlist exemption',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Deleted collaboration allowlist exemption ${exemptionId}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/collaborations.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst leche = require('leche');\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\n\ndescribe('Collaborations', function () {\n\tdescribe('collaborations:get', function () {\n\t\tlet collaborationId = '1234567890',\n\t\t\tfixture = getFixture('collaborations/get_collaborations_id'),\n\t\t\tyamlOutput = getFixture('output/collaborations_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/collaborations/${collaborationId}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collaborations:get',\n\t\t\t\tcollaborationId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get an individual collaboration (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/collaborations/${collaborationId}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['collaborations:get', collaborationId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get an individual collaboration (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/collaborations/${collaborationId}`)\n\t\t\t\t.query({ fields: 'status,role' })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collaborations:get',\n\t\t\t\tcollaborationId,\n\t\t\t\t'--fields=status,role',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param and filter output when --fields flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet lb = '\\n';\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`Type: collaboration${lb}ID: '1234567890'${lb}Status: accepted${lb}Role: editor${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tleche.withData(\n\t\t[\n\t\t\t'collaborations:update',\n\t\t\t'files:collaborations:update',\n\t\t\t'folders:collaborations:update',\n\t\t],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet collaborationId = '1234567890',\n\t\t\t\t\tfixture = getFixture(\n\t\t\t\t\t\t'collaborations/put_collaborations_id'\n\t\t\t\t\t),\n\t\t\t\t\tyamlOutput = getFixture(\n\t\t\t\t\t\t'output/collaborations_update_yaml.txt'\n\t\t\t\t\t);\n\n\t\t\t\tlet collaborationBody = {\n\t\t\t\t\trole: 'viewer',\n\t\t\t\t\tstatus: 'accepted',\n\t\t\t\t};\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(\n\t\t\t\t\t\t\t`/2.0/collaborations/${collaborationId}`,\n\t\t\t\t\t\t\tcollaborationBody\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tcollaborationId,\n\t\t\t\t\t\t'--viewer',\n\t\t\t\t\t\t'--status=accepted',\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should update a collaboration with viewer and status flags passed (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(\n\t\t\t\t\t\t\t`/2.0/collaborations/${collaborationId}`,\n\t\t\t\t\t\t\tcollaborationBody\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tcollaborationId,\n\t\t\t\t\t\t'--viewer',\n\t\t\t\t\t\t'--status=accepted',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should update a collaboration with viewer and status flags passed (YAML Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(`/2.0/collaborations/${collaborationId}`, {\n\t\t\t\t\t\t\trole: 'owner',\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(204)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.stderr()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tcollaborationId,\n\t\t\t\t\t\t'--role=owner',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should print a success message after updating collab role to owner',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t\t\t`Collaborator successfully upgraded to owner.${os.EOL}`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\tleche.withData(\n\t\t\t\t\t{\n\t\t\t\t\t\t'editor flag': ['--editor', 'editor'],\n\t\t\t\t\t\t'previewer flag': ['--previewer', 'previewer'],\n\t\t\t\t\t\t'uploader flag': ['--uploader', 'uploader'],\n\t\t\t\t\t\t'previewer-uploader flag': [\n\t\t\t\t\t\t\t'--previewer-uploader',\n\t\t\t\t\t\t\t'previewer uploader',\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'viewer-uploader flag': [\n\t\t\t\t\t\t\t'--viewer-uploader',\n\t\t\t\t\t\t\t'viewer uploader',\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'co-owner flag': ['--co-owner', 'co-owner'],\n\t\t\t\t\t\t'owner flag': ['--owner', 'owner'],\n\t\t\t\t\t\t'role flag set to editor': ['--role=editor', 'editor'],\n\t\t\t\t\t\t'role flag set to co-owner': [\n\t\t\t\t\t\t\t'--role=co-owner',\n\t\t\t\t\t\t\t'co-owner',\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'role flag set to viewer uploader': [\n\t\t\t\t\t\t\t'--role=viewer_uploader',\n\t\t\t\t\t\t\t'viewer uploader',\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\tfunction (roleFlag, roleValue) {\n\t\t\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\t\t\tapi\n\t\t\t\t\t\t\t\t.put(`/2.0/collaborations/${collaborationId}`, {\n\t\t\t\t\t\t\t\t\t...collaborationBody,\n\t\t\t\t\t\t\t\t\trole: roleValue,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.stdout()\n\t\t\t\t\t\t\t.command([\n\t\t\t\t\t\t\t\tcommand,\n\t\t\t\t\t\t\t\tcollaborationId,\n\t\t\t\t\t\t\t\troleFlag,\n\t\t\t\t\t\t\t\t'--status=accepted',\n\t\t\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t\t.it(\n\t\t\t\t\t\t\t\t'should create a collaboration with the correct role when passed flag for role',\n\t\t\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(\n\t\t\t\t\t\t\t`/2.0/collaborations/${collaborationId}`,\n\t\t\t\t\t\t\tcollaborationBody\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.query({ fields: 'status,role' })\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tcollaborationId,\n\t\t\t\t\t\t'--viewer',\n\t\t\t\t\t\t'--fields=status,role',\n\t\t\t\t\t\t'--status=accepted',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should send fields param and filter output when --fields flag is passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tlet lb = '\\n';\n\t\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t\t\t`Type: collaboration${lb}ID: '1234567890'${lb}Status: accepted${lb}Role: viewer${os.EOL}`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\tleche.withData(\n\t\t\t\t\t{\n\t\t\t\t\t\t'can-view-path flag': ['--can-view-path', true],\n\t\t\t\t\t\t'no-can-view-path flag': ['--no-can-view-path', false],\n\t\t\t\t\t},\n\t\t\t\t\tfunction (viewPathFlag, canViewPathValue) {\n\t\t\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\t\t\tapi\n\t\t\t\t\t\t\t\t.put(`/2.0/collaborations/${collaborationId}`, {\n\t\t\t\t\t\t\t\t\t...collaborationBody,\n\t\t\t\t\t\t\t\t\tcan_view_path: canViewPathValue,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.stdout()\n\t\t\t\t\t\t\t.command([\n\t\t\t\t\t\t\t\tcommand,\n\t\t\t\t\t\t\t\tcollaborationId,\n\t\t\t\t\t\t\t\t'--viewer',\n\t\t\t\t\t\t\t\tviewPathFlag,\n\t\t\t\t\t\t\t\t'--status=accepted',\n\t\t\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t\t.it(\n\t\t\t\t\t\t\t\t'should send can_view_path value when --can-view-path flag is passed',\n\t\t\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\t\tlet expiresAt = '2020-01-01T08:00:00+00:00';\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(`/2.0/collaborations/${collaborationId}`, {\n\t\t\t\t\t\t\trole: 'viewer',\n\t\t\t\t\t\t\texpires_at: expiresAt,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tcollaborationId,\n\t\t\t\t\t\t'--viewer',\n\t\t\t\t\t\t`--expires-at=${expiresAt}`,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should send expires_at value when --expires-at flag is passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tleche.withData(\n\t\t[\n\t\t\t'collaborations:delete',\n\t\t\t'files:collaborations:delete',\n\t\t\t'folders:collaborations:delete',\n\t\t],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet collaborationId = '1234567890';\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.delete(`/2.0/collaborations/${collaborationId}`)\n\t\t\t\t\t\t.reply(204)\n\t\t\t\t)\n\t\t\t\t\t.stderr()\n\t\t\t\t\t.command([command, collaborationId, '--token=test'])\n\t\t\t\t\t.it('should remove a collaboration', (context) => {\n\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t\t`Collaboration ${collaborationId} successfully removed${os.EOL}`\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t});\n\t\t}\n\t);\n\n\tleche.withData(\n\t\t['collaborations:create', 'collaborations:add'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet itemId = '1234567890',\n\t\t\t\t\tboxItemType = 'folder',\n\t\t\t\t\tcollaborationId = '1234567890',\n\t\t\t\t\tuserID = '12345',\n\t\t\t\t\tgroupID = '54321',\n\t\t\t\t\taddCollaborationFixture = getFixture(\n\t\t\t\t\t\t'collaborations/post_collaborations_user'\n\t\t\t\t\t),\n\t\t\t\t\tyamlOutput = getFixture(\n\t\t\t\t\t\t'output/collaborations_add_login_yaml.txt'\n\t\t\t\t\t);\n\n\t\t\t\tlet addCollaborationBody = {\n\t\t\t\t\titem: {\n\t\t\t\t\t\ttype: 'folder',\n\t\t\t\t\t\tid: itemId,\n\t\t\t\t\t},\n\t\t\t\t\taccessible_by: {\n\t\t\t\t\t\ttype: 'user',\n\t\t\t\t\t\tlogin: 'newfriend@example.com',\n\t\t\t\t\t},\n\t\t\t\t\trole: 'previewer',\n\t\t\t\t};\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post('/2.0/collaborations', addCollaborationBody)\n\t\t\t\t\t\t.reply(201, addCollaborationFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\titemId,\n\t\t\t\t\t\tboxItemType,\n\t\t\t\t\t\t'--previewer',\n\t\t\t\t\t\t'--login=newfriend@example.com',\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should output JSON when the --json flag is passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t\t\taddCollaborationFixture\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post('/2.0/collaborations', addCollaborationBody)\n\t\t\t\t\t\t.reply(201, addCollaborationFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\titemId,\n\t\t\t\t\t\tboxItemType,\n\t\t\t\t\t\t'--previewer',\n\t\t\t\t\t\t'--login=newfriend@example.com',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should create a collaboration for a Box item with the viewer and login flags passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post('/2.0/collaborations', addCollaborationBody)\n\t\t\t\t\t\t.reply(201, addCollaborationFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\titemId,\n\t\t\t\t\t\tboxItemType,\n\t\t\t\t\t\t'--previewer',\n\t\t\t\t\t\t'--login=newfriend@example.com',\n\t\t\t\t\t\t'--id-only',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should output only the ID of the created collaboration when the --id-only flag is passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t\t\t`${collaborationId}${os.EOL}`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\tleche.withData(\n\t\t\t\t\t{\n\t\t\t\t\t\t'editor flag': ['--editor', 'editor'],\n\t\t\t\t\t\t'viewer flag': ['--viewer', 'viewer'],\n\t\t\t\t\t\t'uploader flag': ['--uploader', 'uploader'],\n\t\t\t\t\t\t'previewer-uploader flag': [\n\t\t\t\t\t\t\t'--previewer-uploader',\n\t\t\t\t\t\t\t'previewer uploader',\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'viewer-uploader flag': [\n\t\t\t\t\t\t\t'--viewer-uploader',\n\t\t\t\t\t\t\t'viewer uploader',\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'co-owner flag': ['--co-owner', 'co-owner'],\n\t\t\t\t\t\t'role flag set to editor': ['--role=editor', 'editor'],\n\t\t\t\t\t\t'role flag set to co-owner': [\n\t\t\t\t\t\t\t'--role=co-owner',\n\t\t\t\t\t\t\t'co-owner',\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'role flag set to viewer uploader': [\n\t\t\t\t\t\t\t'--role=viewer_uploader',\n\t\t\t\t\t\t\t'viewer uploader',\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\tfunction (roleFlag, roleValue) {\n\t\t\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\t\t\tapi\n\t\t\t\t\t\t\t\t.post('/2.0/collaborations', {\n\t\t\t\t\t\t\t\t\t...addCollaborationBody,\n\t\t\t\t\t\t\t\t\trole: roleValue,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.reply(201, addCollaborationFixture)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.stdout()\n\t\t\t\t\t\t\t.command([\n\t\t\t\t\t\t\t\tcommand,\n\t\t\t\t\t\t\t\titemId,\n\t\t\t\t\t\t\t\tboxItemType,\n\t\t\t\t\t\t\t\troleFlag,\n\t\t\t\t\t\t\t\t'--login=newfriend@example.com',\n\t\t\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t\t.it(\n\t\t\t\t\t\t\t\t'should create a collaboration with the correct role when passed flag for role',\n\t\t\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\t\tleche.withData(\n\t\t\t\t\t{\n\t\t\t\t\t\t'notify flag': ['--notify', true],\n\t\t\t\t\t\t'no-notify flag': ['--no-notify', false],\n\t\t\t\t\t},\n\t\t\t\t\tfunction (notifyFlag, notifyValue) {\n\t\t\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\t\t\tapi\n\t\t\t\t\t\t\t\t.post(\n\t\t\t\t\t\t\t\t\t'/2.0/collaborations',\n\t\t\t\t\t\t\t\t\taddCollaborationBody\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t.query({ notify: notifyValue })\n\t\t\t\t\t\t\t\t.reply(201, addCollaborationFixture)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.stdout()\n\t\t\t\t\t\t\t.command([\n\t\t\t\t\t\t\t\tcommand,\n\t\t\t\t\t\t\t\titemId,\n\t\t\t\t\t\t\t\tboxItemType,\n\t\t\t\t\t\t\t\t'--previewer',\n\t\t\t\t\t\t\t\tnotifyFlag,\n\t\t\t\t\t\t\t\t'--login=newfriend@example.com',\n\t\t\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t\t.it(\n\t\t\t\t\t\t\t\t'should send notify query param when --notify flag is passed',\n\t\t\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post('/2.0/collaborations', addCollaborationBody)\n\t\t\t\t\t\t.query({ fields: 'status,role' })\n\t\t\t\t\t\t.reply(201, addCollaborationFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\titemId,\n\t\t\t\t\t\tboxItemType,\n\t\t\t\t\t\t'--previewer',\n\t\t\t\t\t\t'--fields=status,role',\n\t\t\t\t\t\t'--login=newfriend@example.com',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should send fields param and filter output when --fields flag is passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tlet lb = '\\n';\n\t\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t\t\t`Type: collaboration${lb}ID: '1234567890'${lb}Status: accepted${lb}Role: previewer${os.EOL}`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\tleche.withData(\n\t\t\t\t\t{\n\t\t\t\t\t\t'can-view-path flag': ['--can-view-path', true],\n\t\t\t\t\t\t'no-can-view-path flag': ['--no-can-view-path', false],\n\t\t\t\t\t},\n\t\t\t\t\tfunction (viewPathFlag, canViewPathValue) {\n\t\t\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\t\t\tapi\n\t\t\t\t\t\t\t\t.post('/2.0/collaborations', {\n\t\t\t\t\t\t\t\t\t...addCollaborationBody,\n\t\t\t\t\t\t\t\t\tcan_view_path: canViewPathValue,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.reply(201, addCollaborationFixture)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.stdout()\n\t\t\t\t\t\t\t.command([\n\t\t\t\t\t\t\t\tcommand,\n\t\t\t\t\t\t\t\titemId,\n\t\t\t\t\t\t\t\tboxItemType,\n\t\t\t\t\t\t\t\t'--previewer',\n\t\t\t\t\t\t\t\tviewPathFlag,\n\t\t\t\t\t\t\t\t'--login=newfriend@example.com',\n\t\t\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t\t.it(\n\t\t\t\t\t\t\t\t'should send notify query param when --notify flag is passed',\n\t\t\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post('/2.0/collaborations', {\n\t\t\t\t\t\t\t...addCollaborationBody,\n\t\t\t\t\t\t\taccessible_by: {\n\t\t\t\t\t\t\t\ttype: 'user',\n\t\t\t\t\t\t\t\tid: userID,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(201, addCollaborationFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\titemId,\n\t\t\t\t\t\tboxItemType,\n\t\t\t\t\t\t'--previewer',\n\t\t\t\t\t\t`--user-id=${userID}`,\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should create collaboration for user by ID when --user-id flag is passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post('/2.0/collaborations', {\n\t\t\t\t\t\t\t...addCollaborationBody,\n\t\t\t\t\t\t\taccessible_by: {\n\t\t\t\t\t\t\t\ttype: 'group',\n\t\t\t\t\t\t\t\tid: groupID,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(201, addCollaborationFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\titemId,\n\t\t\t\t\t\tboxItemType,\n\t\t\t\t\t\t'--previewer',\n\t\t\t\t\t\t`--group-id=${groupID}`,\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should create collaboration for user by ID when --user-id flag is passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tleche.withData(\n\t\t['collaborations:get-pending', 'collaborations:pending'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet fixture = getFixture(\n\t\t\t\t\t\t'collaborations/get_collaborations_pending_page_1'\n\t\t\t\t\t),\n\t\t\t\t\tfixture2 = getFixture(\n\t\t\t\t\t\t'collaborations/get_collaborations_pending_page_2'\n\t\t\t\t\t),\n\t\t\t\t\tjsonOutput = getFixture(\n\t\t\t\t\t\t'output/collaborations_get_pending_json.txt'\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get('/2.0/collaborations')\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\tstatus: 'pending',\n\t\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t.get('/2.0/collaborations')\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\tstatus: 'pending',\n\t\t\t\t\t\t\toffset: 1,\n\t\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, '--json', '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should list all pending collaborations for a user (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n});\n"
  },
  {
    "path": "test/commands/collections.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst { assert } = require('chai');\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\nconst leche = require('leche');\n\ndescribe('Collections', function () {\n\tdescribe('collections', function () {\n\t\tlet fixture = getFixture('collections/get_collections'),\n\t\t\tjsonOutput = getFixture('output/collections_get_json.txt'),\n\t\t\ttableOutput = getFixture('output/collections_get_table.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get('/2.0/collections').reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['collections', '--json', '--token=test'])\n\t\t\t.it('should get your collections (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get('/2.0/collections').reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['collections', '--token=test'])\n\t\t\t.it('should get your collections (Table Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, tableOutput);\n\t\t\t});\n\t});\n\n\tdescribe('collections:items', function () {\n\t\tlet collectionId = '1234567890',\n\t\t\tfixture = getFixture('collections/get_collections_id_items_page_1'),\n\t\t\tfixture2 = getFixture(\n\t\t\t\t'collections/get_collections_id_items_page_2'\n\t\t\t),\n\t\t\tjsonOutput = getFixture('output/collections_list_items_json.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/collections/${collectionId}/items`)\n\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get(`/2.0/collections/${collectionId}/items`)\n\t\t\t\t.query({\n\t\t\t\t\toffset: 2,\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collections:items',\n\t\t\t\tcollectionId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should get items in a collection (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/collections/${collectionId}/items`)\n\t\t\t\t.query({ fields: 'name', limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get(`/2.0/collections/${collectionId}/items`)\n\t\t\t\t.query({\n\t\t\t\t\tfields: 'name',\n\t\t\t\t\toffset: 2,\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'collections:items',\n\t\t\t\tcollectionId,\n\t\t\t\t'--fields=name',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('collections:remove', function () {\n\t\tlet itemType = 'file',\n\t\t\tfileId = '1234567890',\n\t\t\tcollectionId = '1234567890',\n\t\t\tgetFileFixture = getFixture('collections/get_files_id'),\n\t\t\tupdatedFileFixture = getFixture('collections/put_files_id');\n\n\t\tlet expectedBody = {\n\t\t\tcollections: [],\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/files/${fileId}`)\n\t\t\t\t.query({\n\t\t\t\t\tfields: 'collections',\n\t\t\t\t})\n\t\t\t\t.reply(200, getFileFixture)\n\t\t\t\t.put(`/2.0/files/${fileId}`, expectedBody)\n\t\t\t\t.reply(200, updatedFileFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'collections:remove',\n\t\t\t\titemType,\n\t\t\t\tfileId,\n\t\t\t\tcollectionId,\n\t\t\t\t'--json',\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should remove an item from a collection', (context) => {\n\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Removed file \"test_file_download.txt\" from collection ${collectionId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tdescribe('collections:add', function () {\n\t\tlet itemID = '1234567890',\n\t\t\tcollectionId = '1234567890',\n\t\t\tgetFileFixture = getFixture('collections/get_files_id'),\n\t\t\tupdatedFileFixture = getFixture('collections/put_files_id');\n\n\t\tlet expectedBody = {\n\t\t\tcollections: [{ id: collectionId }],\n\t\t};\n\n\t\tleche.withData(\n\t\t\t{\n\t\t\t\tfile: ['file'],\n\t\t\t\tfolder: ['folder'],\n\t\t\t\t'web link': ['web_link'],\n\t\t\t},\n\t\t\tfunction (itemType) {\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/${itemType}s/${itemID}`)\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\tfields: 'collections',\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, getFileFixture)\n\t\t\t\t\t\t.put(`/2.0/${itemType}s/${itemID}`, expectedBody)\n\t\t\t\t\t\t.reply(200, updatedFileFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.stderr()\n\t\t\t\t\t.command([\n\t\t\t\t\t\t'collections:add',\n\t\t\t\t\t\titemType,\n\t\t\t\t\t\titemID,\n\t\t\t\t\t\tcollectionId,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should add an item to a collection (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t\t\t`Added ${itemType} \"test_file_download.txt\" to collection ${collectionId}${os.EOL}`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t}\n\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/comments.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\n\ndescribe('Comments', function () {\n\tdescribe('comments:get', function () {\n\t\tlet commentId = '123456789',\n\t\t\tfixture = getFixture('comments/get_comments_id'),\n\t\t\tyamlOutput = getFixture('output/comments_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/comments/${commentId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['comments:get', commentId, '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a comment (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/comments/${commentId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['comments:get', commentId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a comment (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/comments/${commentId}`)\n\t\t\t\t.query({ fields: 'tagged_message' })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'comments:get',\n\t\t\t\tcommentId,\n\t\t\t\t'--fields=tagged_message',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('comments:update', function () {\n\t\tlet commentId = '123456789',\n\t\t\tmessage = 'Looks great!',\n\t\t\ttaggedMessage = '@[1357908642:Other User] Looks good!',\n\t\t\tfixture = getFixture('comments/put_comments_id'),\n\t\t\tyamlOutput = getFixture('output/comments_update_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/comments/${commentId}`, { message })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'comments:update',\n\t\t\t\tcommentId,\n\t\t\t\t`--message=${message}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a comment with the message flag passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/comments/${commentId}`, {\n\t\t\t\t\ttagged_message: taggedMessage,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'comments:update',\n\t\t\t\tcommentId,\n\t\t\t\t`--tagged-message=${taggedMessage}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a comment with the tagged-message flag passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/comments/${commentId}`, { message })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'comments:update',\n\t\t\t\tcommentId,\n\t\t\t\t`--message=${message}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a comment with the message flag passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('comments:delete', function () {\n\t\tlet commentId = '123456789';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.delete(`/2.0/comments/${commentId}`).reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['comments:delete', commentId, '--token=test'])\n\t\t\t.it('should delete a comment', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Successfully deleted comment ${commentId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tdescribe('comments:create', function () {\n\t\tlet fileId = '987654321',\n\t\t\ttaggedMessage = '@[1357908642:Other User] Looks good!',\n\t\t\tmessage = 'Hello there!',\n\t\t\tfixture = getFixture('comments/post_comments'),\n\t\t\tyamlOutput = getFixture('output/comments_create_yaml.txt');\n\n\t\tlet expectedTaggedBody = {\n\t\t\titem: {\n\t\t\t\tid: fileId,\n\t\t\t\ttype: 'file',\n\t\t\t},\n\t\t\ttagged_message: taggedMessage,\n\t\t};\n\n\t\tlet expectedBody = {\n\t\t\titem: {\n\t\t\t\tid: fileId,\n\t\t\t\ttype: 'file',\n\t\t\t},\n\t\t\tmessage,\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/comments', expectedTaggedBody).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'comments:create',\n\t\t\t\tfileId,\n\t\t\t\t`--tagged-message=${taggedMessage}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a tagged comment on a file (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/comments', expectedBody).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'comments:create',\n\t\t\t\tfileId,\n\t\t\t\t`--message=${message}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a comment on a file when message flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/comments', expectedTaggedBody).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'comments:create',\n\t\t\t\tfileId,\n\t\t\t\t`--tagged-message=${taggedMessage}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a tagged comment on a file (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('comments:reply', function () {\n\t\tlet commentId = '5000948880',\n\t\t\tmessage = 'These tigers are cool!',\n\t\t\ttaggedMessage = '@[1357908642:Other User] Looks good!',\n\t\t\tfixture = getFixture('comments/post_comments_reply'),\n\t\t\tyamlOutput = getFixture('output/comments_reply_yaml.txt');\n\n\t\tlet expectedBody = {\n\t\t\titem: {\n\t\t\t\tid: commentId,\n\t\t\t\ttype: 'comment',\n\t\t\t},\n\t\t\tmessage,\n\t\t};\n\n\t\tlet expectedTaggedBody = {\n\t\t\titem: {\n\t\t\t\tid: commentId,\n\t\t\t\ttype: 'comment',\n\t\t\t},\n\t\t\ttagged_message: taggedMessage,\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/comments', expectedBody).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'comments:reply',\n\t\t\t\tcommentId,\n\t\t\t\t`--message=${message}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should reply to a comment (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/comments', expectedTaggedBody).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'comments:reply',\n\t\t\t\tcommentId,\n\t\t\t\t`--tagged-message=${taggedMessage}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should reply to a comment when tagged message flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/comments', expectedBody).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'comments:reply',\n\t\t\t\tcommentId,\n\t\t\t\t`--message=${message}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should reply to a comment (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/commands/configure-environments.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst { assert } = require('chai');\nconst sinon = require('sinon');\nconst BoxCommand = require('../../src/box-command');\n\ndescribe('Configure environments masking', function () {\n\tlet sandbox;\n\tlet getEnvironmentsStub;\n\tlet updateEnvironmentsStub;\n\n\tconst RAW_SECRET = 'abcdefghijklmnopqrstuvwxyz123456';\n\tconst MASKED_SECRET = `${'*'.repeat(RAW_SECRET.length - 3)}${RAW_SECRET.slice(-3)}`;\n\n\tbeforeEach(function () {\n\t\tsandbox = sinon.createSandbox();\n\t\tgetEnvironmentsStub = sandbox.stub(BoxCommand.prototype, 'getEnvironments');\n\t\tupdateEnvironmentsStub = sandbox.stub(\n\t\t\tBoxCommand.prototype,\n\t\t\t'updateEnvironments'\n\t\t);\n\t\tupdateEnvironmentsStub.resolves();\n\t});\n\n\tafterEach(function () {\n\t\tsandbox.restore();\n\t});\n\n\tit('configure:environments:get should not print raw client secrets', function () {\n\t\tgetEnvironmentsStub.resolves({\n\t\t\tdefault: 'dev',\n\t\t\tenvironments: {\n\t\t\t\tdev: {\n\t\t\t\t\tname: 'dev',\n\t\t\t\t\tclientSecret: RAW_SECRET,\n\t\t\t\t},\n\t\t\t},\n\t\t});\n\n\t\treturn test\n\t\t\t.stub(BoxCommand.prototype, 'getEnvironments', getEnvironmentsStub)\n\t\t\t.stdout()\n\t\t\t.command(['configure:environments:get'])\n\t\t\t.it('masks clientSecret in output', (ctx) => {\n\t\t\t\tassert.notInclude(ctx.stdout, RAW_SECRET);\n\t\t\t\tassert.include(ctx.stdout, MASKED_SECRET);\n\t\t\t});\n\t});\n\n\tit(\n\t\t'configure:environments:update should not print raw client secrets',\n\t\tfunction () {\n\t\t\tgetEnvironmentsStub.resolves({\n\t\t\t\tdefault: 'dev',\n\t\t\t\tenvironments: {\n\t\t\t\t\tdev: {\n\t\t\t\t\t\tname: 'dev',\n\t\t\t\t\t\tclientSecret: RAW_SECRET,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\n\t\t\treturn test\n\t\t\t\t.stub(BoxCommand.prototype, 'getEnvironments', getEnvironmentsStub)\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'updateEnvironments',\n\t\t\t\t\tupdateEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command(['configure:environments:update'])\n\t\t\t\t.it('masks clientSecret in output', (ctx) => {\n\t\t\t\t\tassert.notInclude(ctx.stdout, RAW_SECRET);\n\t\t\t\t\tassert.include(ctx.stdout, MASKED_SECRET);\n\t\t\t\t});\n\t\t}\n\t);\n});\n"
  },
  {
    "path": "test/commands/device-pins.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\n\ndescribe('Device Pins', function () {\n\tdescribe('device-pins:get', function () {\n\t\tlet devicePinId = '123456789',\n\t\t\tfixture = getFixture('device-pins/get_device_pinners_id'),\n\t\t\tyamlOutput = getFixture('output/device_pins_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/device_pinners/${devicePinId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['device-pins:get', devicePinId, '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about an individual device pin (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/device_pinners/${devicePinId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['device-pins:get', devicePinId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about an individual device pin (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('device-pins:delete', function () {\n\t\tlet devicePinId = '123456789';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.delete(`/2.0/device_pinners/${devicePinId}`).reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['device-pins:delete', devicePinId, '--token=test'])\n\t\t\t.it('should delete individual device pin', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Deleted device pin ${devicePinId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tdescribe('device-pins', function () {\n\t\tlet enterpriseId = '123456',\n\t\t\tdirection = 'ASC',\n\t\t\tuserMeFixture = getFixture('device-pins/get_users_me'),\n\t\t\tfixture = getFixture('device-pins/get_device_pinners_page_1'),\n\t\t\tfixture2 = getFixture('device-pins/get_device_pinners_page_2'),\n\t\t\tjsonOutput = getFixture('output/device_pins_list_json.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/users/me')\n\t\t\t\t.query({\n\t\t\t\t\tfields: 'enterprise',\n\t\t\t\t})\n\t\t\t\t.reply(200, userMeFixture)\n\t\t\t\t.get(`/2.0/enterprises/${enterpriseId}/device_pinners`)\n\t\t\t\t.query({ direction, limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get(`/2.0/enterprises/${enterpriseId}/device_pinners`)\n\t\t\t\t.query({\n\t\t\t\t\tdirection,\n\t\t\t\t\tmarker: 'ZDEF67',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'device-pins',\n\t\t\t\t`--direction=${direction}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should list all the device pins within a given enterprise with the direction flag passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/events.test.js",
    "content": "'use strict';\nconst { test } = require('@oclif/test');\nconst { assert } = require('chai');\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst leche = require('leche');\n\nfunction assertQuery(\n\tquery,\n\tstreamType,\n\texpectedBeforeDate,\n\texpectedAfterDate,\n\tstreamPosition\n) {\n\tconst beforeDate = new Date(query.created_before);\n\tconst afterDate = new Date(query.created_after);\n\treturn (\n\t\tquery.stream_type === streamType &&\n\t\t((!streamPosition && !query.stream_position) ||\n\t\t\tstreamPosition === query.stream_position) &&\n\t\tbeforeDate.getFullYear() === expectedBeforeDate.getFullYear() &&\n\t\tbeforeDate.getMonth() === expectedBeforeDate.getMonth() &&\n\t\tbeforeDate.getDay() === expectedBeforeDate.getDay() &&\n\t\tafterDate.getFullYear() === expectedAfterDate.getFullYear() &&\n\t\tafterDate.getMonth() === expectedAfterDate.getMonth() &&\n\t\tafterDate.getDay() === expectedAfterDate.getDay()\n\t);\n}\n\nfunction minusDays(date, daysToSubtract) {\n\tdate.setDate(date.getDate() - daysToSubtract);\n\treturn date;\n}\n\ndescribe('Events', function () {\n\tconst createdBefore = '2014-05-17T13:35:01+00:00';\n\tconst createdAfter = '2015-05-15T13:35:01+00:00';\n\tconst eventType = 'NEW_USER,DELETE_USER,EDIT_USER';\n\tconst streamPosition = '122333';\n\tconst fixture = getFixture('events/get_events');\n\tconst fixture2 = getFixture('events/get_events_second_page');\n\tconst endFixture = getFixture('events/get_events_end');\n\tconst jsonOutput = getFixture('output/events_get_json.txt');\n\n\tdescribe('For admin_logs stream type', function () {\n\t\tleche.withData(['events', 'events:get'], function (command) {\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tcreated_before: createdBefore,\n\t\t\t\t\t\tcreated_after: createdAfter,\n\t\t\t\t\t\tevent_type: eventType,\n\t\t\t\t\t\tstream_type: 'admin_logs',\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tcreated_before: createdBefore,\n\t\t\t\t\t\tcreated_after: createdAfter,\n\t\t\t\t\t\tevent_type: eventType,\n\t\t\t\t\t\tstream_type: 'admin_logs',\n\t\t\t\t\t\tstream_position:\n\t\t\t\t\t\t\tJSON.parse(fixture).next_stream_position,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tcreated_before: createdBefore,\n\t\t\t\t\t\tcreated_after: createdAfter,\n\t\t\t\t\t\tevent_type: eventType,\n\t\t\t\t\t\tstream_type: 'admin_logs',\n\t\t\t\t\t\tstream_position:\n\t\t\t\t\t\t\tJSON.parse(fixture2).next_stream_position,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, endFixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\t'--enterprise',\n\t\t\t\t\t`--created-before=${createdBefore}`,\n\t\t\t\t\t`--created-after=${createdAfter}`,\n\t\t\t\t\t`--event-types=${eventType}`,\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should get events with enterprise, created-before, created-after and event-types flags passed (JSON Output)',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tcreated_before: createdBefore,\n\t\t\t\t\t\tcreated_after: createdAfter,\n\t\t\t\t\t\tevent_type: eventType,\n\t\t\t\t\t\tstream_type: 'admin_logs',\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tcreated_before: createdBefore,\n\t\t\t\t\t\tcreated_after: createdAfter,\n\t\t\t\t\t\tevent_type: eventType,\n\t\t\t\t\t\tstream_type: 'admin_logs',\n\t\t\t\t\t\tstream_position:\n\t\t\t\t\t\t\tJSON.parse(fixture).next_stream_position,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tcreated_before: createdBefore,\n\t\t\t\t\t\tcreated_after: createdAfter,\n\t\t\t\t\t\tevent_type: eventType,\n\t\t\t\t\t\tstream_type: 'admin_logs',\n\t\t\t\t\t\tstream_position:\n\t\t\t\t\t\t\tJSON.parse(fixture2).next_stream_position,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, endFixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\t'--enterprise',\n\t\t\t\t\t'--stream-type=admin_logs',\n\t\t\t\t\t`--created-before=${createdBefore}`,\n\t\t\t\t\t`--created-after=${createdAfter}`,\n\t\t\t\t\t`--event-types=${eventType}`,\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should get events with enterprise, streamType, created-before, created-after and event-types flags passed (JSON Output)',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tstream_position: streamPosition,\n\t\t\t\t\t\tlimit: '10',\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\t`--stream-position=${streamPosition}`,\n\t\t\t\t\t'--limit=10',\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should get user events from given stream position when --stream-position flag is passed',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tlimit: '10',\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([command, '--limit=10', '--json', '--token=test'])\n\t\t\t\t.it(\n\t\t\t\t\t'should get user events when neither --stream-position nor --enterprise flags are passed',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query((query) =>\n\t\t\t\t\t\tassertQuery(\n\t\t\t\t\t\t\tquery,\n\t\t\t\t\t\t\t'admin_logs',\n\t\t\t\t\t\t\tnew Date(),\n\t\t\t\t\t\t\tminusDays(new Date(), 5),\n\t\t\t\t\t\t\tnull\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query((query) =>\n\t\t\t\t\t\tassertQuery(\n\t\t\t\t\t\t\tquery,\n\t\t\t\t\t\t\t'admin_logs',\n\t\t\t\t\t\t\tnew Date(),\n\t\t\t\t\t\t\tminusDays(new Date(), 5),\n\t\t\t\t\t\t\tJSON.parse(fixture).next_stream_position\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query((query) =>\n\t\t\t\t\t\tassertQuery(\n\t\t\t\t\t\t\tquery,\n\t\t\t\t\t\t\t'admin_logs',\n\t\t\t\t\t\t\tnew Date(),\n\t\t\t\t\t\t\tminusDays(new Date(), 5),\n\t\t\t\t\t\t\tJSON.parse(fixture2).next_stream_position\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t\t.reply(200, endFixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([command, '--enterprise', '--json', '--token=test'])\n\t\t\t\t.it(\n\t\t\t\t\t'should use default time window when no time bound flags are passed',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tcreated_before: '2019-02-11T12:34:56+00:00',\n\t\t\t\t\t\tcreated_after: '2019-02-06T12:34:56+00:00',\n\t\t\t\t\t\tstream_type: 'admin_logs',\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tcreated_before: '2019-02-11T12:34:56+00:00',\n\t\t\t\t\t\tcreated_after: '2019-02-06T12:34:56+00:00',\n\t\t\t\t\t\tstream_type: 'admin_logs',\n\t\t\t\t\t\tstream_position:\n\t\t\t\t\t\t\tJSON.parse(fixture).next_stream_position,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tcreated_before: '2019-02-11T12:34:56+00:00',\n\t\t\t\t\t\tcreated_after: '2019-02-06T12:34:56+00:00',\n\t\t\t\t\t\tstream_type: 'admin_logs',\n\t\t\t\t\t\tstream_position:\n\t\t\t\t\t\t\tJSON.parse(fixture2).next_stream_position,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, endFixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\t'--enterprise',\n\t\t\t\t\t'--created-before=2019-02-11T12:34:56+00:00',\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should set start time to five days before end time when only end time is passed',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query((query) =>\n\t\t\t\t\t\tassertQuery(\n\t\t\t\t\t\t\tquery,\n\t\t\t\t\t\t\t'admin_logs',\n\t\t\t\t\t\t\tnew Date(),\n\t\t\t\t\t\t\tnew Date('2018-01-01T12:34:56+00:00')\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query((query) =>\n\t\t\t\t\t\tassertQuery(\n\t\t\t\t\t\t\tquery,\n\t\t\t\t\t\t\t'admin_logs',\n\t\t\t\t\t\t\tnew Date(),\n\t\t\t\t\t\t\tnew Date('2018-01-01T12:34:56+00:00'),\n\t\t\t\t\t\t\tJSON.parse(fixture).next_stream_position\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query((query) =>\n\t\t\t\t\t\tassertQuery(\n\t\t\t\t\t\t\tquery,\n\t\t\t\t\t\t\t'admin_logs',\n\t\t\t\t\t\t\tnew Date(),\n\t\t\t\t\t\t\tnew Date('2018-01-01T12:34:56+00:00'),\n\t\t\t\t\t\t\tJSON.parse(fixture2).next_stream_position\n\t\t\t\t\t\t)\n\t\t\t\t\t)\n\t\t\t\t\t.reply(200, endFixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\t'--enterprise',\n\t\t\t\t\t'--created-after=2018-01-01T12:34:56+00:00',\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should set end time to now when only start time is passed',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t});\n\t\t//\tdescribe.only('events:poll', () => {\n\t\t//\t\tvar stream = fs.createReadStream(path.join(__dirname, '..', 'fixtures/test_file.txt'));\n\t\t//\n\t\t//\t\ttest\n\t\t//\t\t\t.nock(TEST_API_ROOT, api => api\n\t\t//\t\t\t\t.options('/2.0/events')\n\t\t//\t\t\t\t.query(true)\n\t\t//\t\t\t\t.reply(200, () => stream)\n\t\t//\t\t\t)\n\t\t//\t\t\t.stdout()\n\t\t//\t\t\t.command([\n\t\t//\t\t\t\t'events:poll',\n\t\t//\t\t\t\t'--json'\n\t\t//\t\t\t])\n\t\t//\t\t\t.it('should poll the event stream', ctx => {\n\t\t//\t\t\t\t//\t\t\t\tstream.on('data', function (chunk) {\n\t\t//\t\t\t\t//\t\t\t\t\tconsole.log(chunk);\n\t\t//\t\t\t\t//\t\t\t\t});\n\t\t//\t\t\t\t//\t\t\t\tassert.deepEqual(JSON.parse(ctx.stdout), JSON.parse(fixture));\n\t\t//\t\t\t});\n\t\t//\t});\n\t});\n\n\tdescribe('For admin_logs_streaming stream type', function () {\n\t\tleche.withData(['events', 'events:get'], function (command) {\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query(\n\t\t\t\t\t\t(query) =>\n\t\t\t\t\t\t\t!query.stream_position &&\n\t\t\t\t\t\t\tquery.event_type === eventType &&\n\t\t\t\t\t\t\tquery.stream_type === 'admin_logs_streaming'\n\t\t\t\t\t)\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tevent_type: eventType,\n\t\t\t\t\t\tstream_type: 'admin_logs_streaming',\n\t\t\t\t\t\tstream_position:\n\t\t\t\t\t\t\tJSON.parse(fixture).next_stream_position,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tevent_type: eventType,\n\t\t\t\t\t\tstream_type: 'admin_logs_streaming',\n\t\t\t\t\t\tstream_position:\n\t\t\t\t\t\t\tJSON.parse(fixture2).next_stream_position,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, endFixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\t'--enterprise',\n\t\t\t\t\t'--stream-type=admin_logs_streaming',\n\t\t\t\t\t`--event-types=${eventType}`,\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should get events with enterprise, event-types flags passed (JSON Output)',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query(\n\t\t\t\t\t\t(query) =>\n\t\t\t\t\t\t\t!query.stream_position &&\n\t\t\t\t\t\t\tquery.event_type === eventType &&\n\t\t\t\t\t\t\tquery.stream_type === 'admin_logs_streaming'\n\t\t\t\t\t)\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tevent_type: eventType,\n\t\t\t\t\t\tstream_type: 'admin_logs_streaming',\n\t\t\t\t\t\tstream_position:\n\t\t\t\t\t\t\tJSON.parse(fixture).next_stream_position,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tevent_type: eventType,\n\t\t\t\t\t\tstream_type: 'admin_logs_streaming',\n\t\t\t\t\t\tstream_position:\n\t\t\t\t\t\t\tJSON.parse(fixture2).next_stream_position,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, endFixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\t'--enterprise',\n\t\t\t\t\t'--stream-type=admin_logs_streaming',\n\t\t\t\t\t`--event-types=${eventType}`,\n\t\t\t\t\t`--created-before=${createdBefore}`,\n\t\t\t\t\t`--created-after=${createdAfter}`,\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should should ignore created-xxx flags (JSON Output)',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/events')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tstream_type: 'admin_logs_streaming',\n\t\t\t\t\t\tstream_position: streamPosition,\n\t\t\t\t\t\tlimit: '10',\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\t'--enterprise',\n\t\t\t\t\t'--stream-type=admin_logs_streaming',\n\t\t\t\t\t`--stream-position=${streamPosition}`,\n\t\t\t\t\t'--limit=10',\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should get user events from given stream position when --stream-position flag is passed',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/commands/file-requests.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\n\ndescribe('File Requests', function () {\n\tdescribe('file-requests:get', function () {\n\t\tlet fileRequestId = '123456789',\n\t\t\tfixture = getFixture('file-requests/get_file_requests_id'),\n\t\t\tyamlOutput = getFixture('output/file_requests_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/file_requests/${fileRequestId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'file-requests:get',\n\t\t\t\tfileRequestId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information about an individual file request (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/file_requests/${fileRequestId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['file-requests:get', fileRequestId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about an individual file request (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('file-requests:delete', function () {\n\t\tlet fileRequestId = '123456789';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.delete(`/2.0/file_requests/${fileRequestId}`).reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['file-requests:delete', fileRequestId, '--token=test'])\n\t\t\t.it('should delete individual file request', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Deleted file request ${fileRequestId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tlet fileRequestId = '1234567890',\n\t\tparentFolderId = '987654321';\n\n\tlet requestBody = {\n\t\tfolder: {\n\t\t\tid: parentFolderId,\n\t\t\ttype: 'folder',\n\t\t},\n\t};\n\n\tlet title = 'New title';\n\tlet description = 'New Description';\n\tlet expiresAt = '2023-01-01T08:00:00+00:00';\n\tlet status = 'active';\n\n\tlet addParameters = {\n\t\ttitle,\n\t\tdescription,\n\t\texpires_at: expiresAt,\n\t\tis_description_required: true,\n\t\tis_email_required: true,\n\t\tstatus,\n\t};\n\n\tlet addFlags = [\n\t\t`--title=${title}`,\n\t\t`--description=${description}`,\n\t\t`--expires-at=${expiresAt}`,\n\t\t'--description-required',\n\t\t'--email-required',\n\t\t`--status=${status}`,\n\t];\n\n\tdescribe('file-requests:update', function () {\n\t\tlet updateFixture = getFixture('file-requests/put_file_requests_id'),\n\t\t\tyamlOutput = getFixture('output/file_requests_update_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/file_requests/${fileRequestId}`, {\n\t\t\t\t\t...addParameters,\n\t\t\t\t})\n\t\t\t\t.reply(200, updateFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'file-requests:update',\n\t\t\t\tfileRequestId,\n\t\t\t\t...addFlags,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should update a file request (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, updateFixture);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/file_requests/${fileRequestId}`, {\n\t\t\t\t\t...addParameters,\n\t\t\t\t})\n\t\t\t\t.reply(200, updateFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'file-requests:update',\n\t\t\t\tfileRequestId,\n\t\t\t\t...addFlags,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should update a file request (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\t});\n\n\tdescribe('file-requests:copy', function () {\n\t\tlet copyFixture = getFixture(\n\t\t\t\t'file-requests/post_file_requests_id_copy'\n\t\t\t),\n\t\t\tyamlOutput = getFixture('output/file_requests_copy_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/file_requests/${fileRequestId}/copy`, requestBody)\n\t\t\t\t.reply(201, copyFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'file-requests:copy',\n\t\t\t\tfileRequestId,\n\t\t\t\tparentFolderId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should copy a file request to a different folder (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, copyFixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/file_requests/${fileRequestId}/copy`, requestBody)\n\t\t\t\t.reply(201, copyFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'file-requests:copy',\n\t\t\t\tfileRequestId,\n\t\t\t\tparentFolderId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should copy a file request to a different folder (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/file_requests/${fileRequestId}/copy`, {\n\t\t\t\t\t...requestBody,\n\t\t\t\t\t...addParameters,\n\t\t\t\t})\n\t\t\t\t.reply(201, copyFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'file-requests:copy',\n\t\t\t\tfileRequestId,\n\t\t\t\tparentFolderId,\n\t\t\t\t...addFlags,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send optional parameters when optional flags are passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, copyFixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/files.test.js",
    "content": "'use strict';\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst fs = require('node:fs');\nconst path = require('node:path');\nconst {\n\tgetFixture,\n\tTEST_API_ROOT,\n\tTEST_UPLOAD_ROOT,\n\tTEST_DOWNLOAD_ROOT,\n\tDEFAULT_DOWNLOAD_PATH,\n\tgetDownloadProgressBar,\n\ttoUrlPath,\n} = require('../helpers/test-helper');\nconst os = require('node:os');\nconst leche = require('leche');\n\ndescribe('Files', function () {\n\tdescribe('files:get', function () {\n\t\tlet fileId = '1234567890',\n\t\t\tgetFileFixture = getFixture('files/get_files_id'),\n\t\t\tyamlOutput = getFixture('output/files_get_yaml.txt');\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/files/${fileId}`).reply(200, getFileFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['files:get', fileId, '--json', '--token=test'])\n\t\t\t.it(\"should get a file's information (JSON Output)\", (context) => {\n\t\t\t\tassert.equal(context.stdout, getFileFixture);\n\t\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/files/${fileId}`).reply(200, getFileFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['files:get', fileId, '--token=test'])\n\t\t\t.it(\"should get a file's information (YAML Output)\", (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/files/${fileId}`)\n\t\t\t\t.query({ fields: 'comment_count' })\n\t\t\t\t.reply(200, getFileFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:get',\n\t\t\t\tfileId,\n\t\t\t\t'--fields=comment_count',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('files:copy', function () {\n\t\tlet fileId = '1234567890',\n\t\t\tparentFolderId = '987654321',\n\t\t\tnewName = 'Copied file.dat',\n\t\t\tversion = '55555',\n\t\t\tcopyFixture = getFixture('files/post_files_id_copy'),\n\t\t\tyamlOutput = getFixture('output/files_copy_yaml.txt');\n\t\tlet copyBody = {\n\t\t\tparent: {\n\t\t\t\tid: parentFolderId,\n\t\t\t},\n\t\t};\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/files/${fileId}/copy`, copyBody)\n\t\t\t\t.reply(201, copyFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:copy',\n\t\t\t\tfileId,\n\t\t\t\tparentFolderId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should copy a file to a different folder (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, copyFixture);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/files/${fileId}/copy`, copyBody)\n\t\t\t\t.reply(201, copyFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['files:copy', fileId, parentFolderId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should copy a file to a different folder (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/files/${fileId}/copy`, copyBody)\n\t\t\t\t.reply(201, copyFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:copy',\n\t\t\t\tfileId,\n\t\t\t\tparentFolderId,\n\t\t\t\t'--id-only',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should output only the ID of the copied file when --id-only flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.parse(copyFixture).id}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/files/${fileId}/copy`, {\n\t\t\t\t\t...copyBody,\n\t\t\t\t\tname: newName,\n\t\t\t\t\tversion,\n\t\t\t\t})\n\t\t\t\t.reply(201, copyFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:copy',\n\t\t\t\tfileId,\n\t\t\t\tparentFolderId,\n\t\t\t\t`--name=${newName}`,\n\t\t\t\t`--version=${version}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send optional parameters when --name and --version flags are passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, copyFixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('files:move', function () {\n\t\tlet fileId = '1234567890',\n\t\t\tparentFolderId = '987654321',\n\t\t\tmoveFixture = getFixture('files/put_files_id'),\n\t\t\tyamlOutput = getFixture('output/files_move_yaml.txt');\n\t\tlet moveBody = {\n\t\t\tparent: {\n\t\t\t\tid: parentFolderId,\n\t\t\t},\n\t\t};\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.put(`/2.0/files/${fileId}`, moveBody).reply(200, moveFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:move',\n\t\t\t\tfileId,\n\t\t\t\tparentFolderId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should move a file to a different folder (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, moveFixture);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.put(`/2.0/files/${fileId}`, moveBody).reply(200, moveFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['files:move', fileId, parentFolderId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should move a file to a different folder (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/files/${fileId}`, moveBody)\n\t\t\t\t.matchHeader('If-Match', '5')\n\t\t\t\t.reply(412, {\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\tstatus: 412,\n\t\t\t\t\tcode: 'precondition_failed',\n\t\t\t\t\thelp_url: 'http://developers.box.com/docs/#errors',\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t'The resource has been modified. Please retrieve the resource again and retry',\n\t\t\t\t\trequest_id: '1wne91fxf8871ide',\n\t\t\t\t})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:move',\n\t\t\t\tfileId,\n\t\t\t\tparentFolderId,\n\t\t\t\t'--json',\n\t\t\t\t'--no-color',\n\t\t\t\t'--etag=5',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send If-Match header and throw error when etag flag is passed but does not match',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet message =\n\t\t\t\t\t\t'Unexpected API Response [412 Precondition Failed | 1wne91fxf8871ide] precondition_failed - The resource has been modified. Please retrieve the resource again and retry';\n\t\t\t\t\tassert.equal(context.stderr, `${message}${os.EOL}`);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('files:delete', function () {\n\t\tlet fileId = '1234567890';\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.delete(`/2.0/files/${fileId}`).reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['files:delete', fileId, '--token=test'])\n\t\t\t.it('should delete a file', (context) => {\n\t\t\t\tassert.equal(context.stderr, `Deleted file ${fileId}${os.EOL}`);\n\t\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.delete(`/2.0/files/${fileId}`).reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['files:delete', fileId, '--quiet', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should delete a file, but output no information to stderr',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stderr, '');\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(`/2.0/files/${fileId}`)\n\t\t\t\t.reply(204)\n\t\t\t\t.delete(`/2.0/files/${fileId}/trash`)\n\t\t\t\t.reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['files:delete', fileId, '-f', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should permanently delete a file when -f flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Deleted file ${fileId} permanently${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(`/2.0/files/${fileId}`)\n\t\t\t\t.matchHeader('If-Match', '5')\n\t\t\t\t.reply(412, {\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\tstatus: 412,\n\t\t\t\t\tcode: 'precondition_failed',\n\t\t\t\t\thelp_url: 'http://developers.box.com/docs/#errors',\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t'The resource has been modified. Please retrieve the resource again and retry',\n\t\t\t\t\trequest_id: '1wne91fxf8871ide',\n\t\t\t\t})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:delete',\n\t\t\t\tfileId,\n\t\t\t\t'--no-color',\n\t\t\t\t'--etag=5',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send If-Match header and throw error when etag flag is passed but does not match',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet message =\n\t\t\t\t\t\t'Unexpected API Response [412 Precondition Failed | 1wne91fxf8871ide] precondition_failed - The resource has been modified. Please retrieve the resource again and retry';\n\t\t\t\t\tassert.equal(context.stderr, `${message}${os.EOL}`);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(`/2.0/files/${fileId}`)\n\t\t\t\t.reply(204)\n\t\t\t\t.delete(`/2.0/files/${fileId}/trash`)\n\t\t\t\t.reply(404)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['files:delete', fileId, '-f', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should force delete successfully when user does not have trash enabled',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Deleted file ${fileId} permanently${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('files:unlock', function () {\n\t\tlet fileId = '1234567890',\n\t\t\tlockFixture = getFixture('files/put_files_id_lock'),\n\t\t\tyamlOutput = getFixture('output/files_unlock_yaml.txt');\n\t\tlet unlockBody = {\n\t\t\tlock: null,\n\t\t};\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.put(`/2.0/files/${fileId}`, unlockBody).reply(200, lockFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['files:unlock', fileId, '--json', '--token=test'])\n\t\t\t.it('should unlock a file (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, lockFixture);\n\t\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.put(`/2.0/files/${fileId}`, unlockBody).reply(200, lockFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['files:unlock', fileId, '--token=test'])\n\t\t\t.it('should unlock a file (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\t});\n\tleche.withData(['files:lock', 'files:update-lock'], function (command) {\n\t\tdescribe(command, function () {\n\t\t\tlet fileId = '1234567890',\n\t\t\t\texpireTime = '2030-01-01T08:00:00+00:00',\n\t\t\t\tlockFixture = getFixture('files/put_files_id_lock'),\n\t\t\t\tyamlOutput = getFixture('output/files_lock_yaml.txt');\n\t\t\tlet lockBody = {\n\t\t\t\tlock: {\n\t\t\t\t\ttype: 'lock',\n\t\t\t\t},\n\t\t\t};\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.put(`/2.0/files/${fileId}`, lockBody)\n\t\t\t\t\t.reply(200, lockFixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([command, fileId, '--json', '--token=test'])\n\t\t\t\t.it('should lock a file (JSON Output)', (context) => {\n\t\t\t\t\tassert.equal(context.stdout, lockFixture);\n\t\t\t\t});\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.put(`/2.0/files/${fileId}`, lockBody)\n\t\t\t\t\t.reply(200, lockFixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([command, fileId, '--token=test'])\n\t\t\t\t.it('should lock a file (YAML Output)', (context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t});\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.put(`/2.0/files/${fileId}`, {\n\t\t\t\t\t\tlock: {\n\t\t\t\t\t\t\ttype: 'lock',\n\t\t\t\t\t\t\tis_download_prevented: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, lockFixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\tfileId,\n\t\t\t\t\t'--prevent-download',\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should prevent download when the --prevent-download flag is passed',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, lockFixture);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.put(`/2.0/files/${fileId}`, {\n\t\t\t\t\t\tlock: {\n\t\t\t\t\t\t\ttype: 'lock',\n\t\t\t\t\t\t\texpires_at: expireTime,\n\t\t\t\t\t\t},\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, lockFixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\tfileId,\n\t\t\t\t\t`--expires=${expireTime}`,\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should set the expiration time when the --expires flag is passed',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, lockFixture);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t});\n\t});\n\tleche.withData(['files:comments', 'comments:list'], function (command) {\n\t\tdescribe(command, function () {\n\t\t\tlet fileId = '1234567890',\n\t\t\t\tfixture = getFixture('comments/get_files_id_comments_page_1'),\n\t\t\t\tfixture2 = getFixture('comments/get_files_id_comments_page_2'),\n\t\t\t\tjsonOutput = getFixture('output/comments_list_json.txt');\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get(`/2.0/files/${fileId}/comments`)\n\t\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get(`/2.0/files/${fileId}/comments`)\n\t\t\t\t\t.query({\n\t\t\t\t\t\toffset: 2,\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([command, fileId, '--json', '--token=test'])\n\t\t\t\t.it(\n\t\t\t\t\t'should list all comments on a file (JSON Output)',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get(`/2.0/files/${fileId}/comments`)\n\t\t\t\t\t.query({ fields: 'message', limit: 1000 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get(`/2.0/files/${fileId}/comments`)\n\t\t\t\t\t.query({\n\t\t\t\t\t\tfields: 'message',\n\t\t\t\t\t\toffset: 2,\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\tfileId,\n\t\t\t\t\t'--fields=message',\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t\t);\n\t\t});\n\t});\n\tleche.withData(\n\t\t['files:collaborations', 'files:collaborations:list'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet fileId = '1234567890',\n\t\t\t\t\tfixture = getFixture(\n\t\t\t\t\t\t'files/get_files_id_collaborations_page_1'\n\t\t\t\t\t),\n\t\t\t\t\tfixture2 = getFixture(\n\t\t\t\t\t\t'files/get_files_id_collaborations_page_2'\n\t\t\t\t\t),\n\t\t\t\t\tjsonOutput = getFixture(\n\t\t\t\t\t\t'output/files_collaborations_list_json.txt'\n\t\t\t\t\t);\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/files/${fileId}/collaborations`)\n\t\t\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t.get(`/2.0/files/${fileId}/collaborations`)\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\tmarker: 'ZAED53D',\n\t\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, fileId, '--json', '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should list all collaborations on a Box item (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/files/${fileId}/collaborations`)\n\t\t\t\t\t\t.query({ fields: 'accessible_by', limit: 1000 })\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t.get(`/2.0/files/${fileId}/collaborations`)\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\tfields: 'accessible_by',\n\t\t\t\t\t\t\tmarker: 'ZAED53D',\n\t\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tfileId,\n\t\t\t\t\t\t'--fields=accessible_by',\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tdescribe('files:collaborations:add', function () {\n\t\tlet fileId = '1234567890',\n\t\t\taddCollaborationFixture = getFixture(\n\t\t\t\t'files/post_collaborations_user'\n\t\t\t),\n\t\t\tyamlOutput = getFixture('output/files_collaborations_add_yaml.txt');\n\t\tlet addCollaborationBody = {\n\t\t\titem: {\n\t\t\t\ttype: 'file',\n\t\t\t\tid: fileId,\n\t\t\t},\n\t\t\taccessible_by: {\n\t\t\t\ttype: 'user',\n\t\t\t\tlogin: 'newfriend@example.com',\n\t\t\t},\n\t\t\trole: 'previewer',\n\t\t};\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody)\n\t\t\t\t.reply(200, addCollaborationFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:collaborations:add',\n\t\t\t\tfileId,\n\t\t\t\t'--previewer',\n\t\t\t\t'--login=newfriend@example.com',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a collaboration for a Box item (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, addCollaborationFixture);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody)\n\t\t\t\t.reply(200, addCollaborationFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:collaborations:add',\n\t\t\t\tfileId,\n\t\t\t\t'--previewer',\n\t\t\t\t'--login=newfriend@example.com',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a collaboration for a Box item (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody)\n\t\t\t\t.reply(200, addCollaborationFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:collaborations:add',\n\t\t\t\tfileId,\n\t\t\t\t'--previewer',\n\t\t\t\t'--login=newfriend@example.com',\n\t\t\t\t'--id-only',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should output only the ID of the created collaboration when --id-only flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.parse(addCollaborationFixture).id}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody)\n\t\t\t\t.reply(200, addCollaborationFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:collaborations:add',\n\t\t\t\t'--previewer',\n\t\t\t\t'--login=newfriend@example.com',\n\t\t\t\tfileId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should work with args in non-standard order', (context) => {\n\t\t\t\tassert.equal(context.stdout, addCollaborationFixture);\n\t\t\t});\n\t});\n\n\tdescribe('files:rename', function () {\n\t\tlet fileId = '1234567890',\n\t\t\trenameFixture = getFixture('files/put_files_id'),\n\t\t\tyamlOutput = getFixture('output/files_rename_yaml.txt');\n\t\tlet renameBody = {\n\t\t\tname: 'test',\n\t\t\tdescription: 'test description',\n\t\t};\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/files/${fileId}`, renameBody)\n\t\t\t\t.reply(200, renameFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:rename',\n\t\t\t\tfileId,\n\t\t\t\t'test',\n\t\t\t\t'--description=test description',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should rename a file (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, renameFixture);\n\t\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/files/${fileId}`, renameBody)\n\t\t\t\t.reply(200, renameFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:rename',\n\t\t\t\tfileId,\n\t\t\t\t'test',\n\t\t\t\t'--description=test description',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should rename a file (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/files/${fileId}`, renameBody)\n\t\t\t\t.matchHeader('If-Match', '5')\n\t\t\t\t.reply(412, {\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\tstatus: 412,\n\t\t\t\t\tcode: 'precondition_failed',\n\t\t\t\t\thelp_url: 'http://developers.box.com/docs/#errors',\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t'The resource has been modified. Please retrieve the resource again and retry',\n\t\t\t\t\trequest_id: '1wne91fxf8871ide',\n\t\t\t\t})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:rename',\n\t\t\t\tfileId,\n\t\t\t\t'test',\n\t\t\t\t'--description=test description',\n\t\t\t\t'--json',\n\t\t\t\t'--no-color',\n\t\t\t\t'--etag=5',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send If-Match header and throw error when etag flag is passed but does not match',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet message =\n\t\t\t\t\t\t'Unexpected API Response [412 Precondition Failed | 1wne91fxf8871ide] precondition_failed - The resource has been modified. Please retrieve the resource again and retry';\n\t\t\t\t\tassert.equal(context.stderr, `${message}${os.EOL}`);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('files:metadata:get', function () {\n\t\tlet fileId = '1234567890',\n\t\t\tmetadataScope = 'enterprise',\n\t\t\tmetadataTemplate = 'testTemplate',\n\t\t\tgetMetadataFixture = getFixture(\n\t\t\t\t'files/get_files_id_metadata_scope_template'\n\t\t\t),\n\t\t\tyamlOutput = getFixture('output/files_metadata_get_yaml.txt');\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(\n\t\t\t\t\t`/2.0/files/${fileId}/metadata/${metadataScope}/${metadataTemplate}`\n\t\t\t\t)\n\t\t\t\t.reply(200, getMetadataFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:metadata:get',\n\t\t\t\tfileId,\n\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information about a metadata object (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, getMetadataFixture);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(\n\t\t\t\t\t`/2.0/files/${fileId}/metadata/${metadataScope}/${metadataTemplate}`\n\t\t\t\t)\n\t\t\t\t.reply(200, getMetadataFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:metadata:get',\n\t\t\t\tfileId,\n\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information about a metadata object (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\tleche.withData(\n\t\t['files:metadata', 'files:metadata:get-all'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet fileId = '123456789',\n\t\t\t\t\tgetAllMetadataFixture = getFixture(\n\t\t\t\t\t\t'files/get_files_id_metadata'\n\t\t\t\t\t),\n\t\t\t\t\tjsonOutput = getFixture(\n\t\t\t\t\t\t'output/files_metadata_get_all_json.txt'\n\t\t\t\t\t);\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/files/${fileId}/metadata`)\n\t\t\t\t\t\t.reply(200, getAllMetadataFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, fileId, '--json', '--token=test'])\n\t\t\t\t\t.it('should get all metadata on a Box item', (context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t});\n\t\t\t});\n\t\t}\n\t);\n\tleche.withData(\n\t\t['files:metadata:remove', 'files:metadata:delete'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet fileId = '1234567890',\n\t\t\t\t\tmetadataScope = 'enterprise',\n\t\t\t\t\tmetadataTemplate = 'testTemplate';\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.delete(\n\t\t\t\t\t\t\t`/2.0/files/${fileId}/metadata/${metadataScope}/${metadataTemplate}`\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.reply(204)\n\t\t\t\t)\n\t\t\t\t\t.stderr()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tfileId,\n\t\t\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it('should delete metadata from an item', (context) => {\n\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t\t`Successfully deleted metadata ${metadataTemplate}${os.EOL}`\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t});\n\t\t}\n\t);\n\n\tdescribe('files:metadata:update', function () {\n\t\tlet fileId = '1234567890',\n\t\t\tmetadataScope = 'enterprise',\n\t\t\tmetadataTemplate = 'testTemplate',\n\t\t\tgetMetadataFixture = getFixture(\n\t\t\t\t'files/get_files_id_metadata_scope_template'\n\t\t\t),\n\t\t\tyamlOutput = getFixture('output/files_metadata_update_yaml.txt');\n\t\tlet updateMetadataBody = [\n\t\t\t{\n\t\t\t\top: 'test',\n\t\t\t\tpath: '/numReviewsLeft',\n\t\t\t\tvalue: 1,\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'replace',\n\t\t\t\tpath: '/numReviewsLeft',\n\t\t\t\tvalue: 0,\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'copy',\n\t\t\t\tfrom: '/competitiveDocument',\n\t\t\t\tpath: '/restricted',\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'add',\n\t\t\t\tpath: '/reviewedBy/-',\n\t\t\t\tvalue: 'me',\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'replace',\n\t\t\t\tpath: '/readyForRelease',\n\t\t\t\tvalue: 'yes',\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'move',\n\t\t\t\tfrom: '/reviewedBy',\n\t\t\t\tpath: '/approvedBy',\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'add',\n\t\t\t\tpath: '/dateApproved',\n\t\t\t\tvalue: '2018-12-02T11:28:55-08:00',\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'replace',\n\t\t\t\tpath: '/stepsRequiredForRelease',\n\t\t\t\tvalue: [],\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'remove',\n\t\t\t\tpath: '/embargoed',\n\t\t\t},\n\t\t];\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(\n\t\t\t\t\t`/2.0/files/${fileId}/metadata/${metadataScope}/${metadataTemplate}`,\n\t\t\t\t\tupdateMetadataBody\n\t\t\t\t)\n\t\t\t\t.reply(200, getMetadataFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:metadata:update',\n\t\t\t\tfileId,\n\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t'--test=/numReviewsLeft=#1',\n\t\t\t\t'--replace=/numReviewsLeft=#0',\n\t\t\t\t'--copy=/competitiveDocument>/restricted',\n\t\t\t\t'--add=reviewedBy[]=me',\n\t\t\t\t'--replace=/readyForRelease=yes',\n\t\t\t\t'--move=reviewedBy>approvedBy',\n\t\t\t\t'--add=/dateApproved=2018-12-02T11:28:55-08:00',\n\t\t\t\t'--replace=/stepsRequiredForRelease=[]',\n\t\t\t\t'--remove=/embargoed',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should update metadata object (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, getMetadataFixture);\n\t\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(\n\t\t\t\t\t`/2.0/files/${fileId}/metadata/${metadataScope}/${metadataTemplate}`,\n\t\t\t\t\tupdateMetadataBody\n\t\t\t\t)\n\t\t\t\t.reply(200, getMetadataFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:metadata:update',\n\t\t\t\tfileId,\n\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t'--test=/numReviewsLeft=#1',\n\t\t\t\t'--replace=/numReviewsLeft=#0',\n\t\t\t\t'--copy=/competitiveDocument>/restricted',\n\t\t\t\t'--add=reviewedBy[]=me',\n\t\t\t\t'--replace=/readyForRelease=yes',\n\t\t\t\t'--move=reviewedBy>approvedBy',\n\t\t\t\t'--add=/dateApproved=2018-12-02T11:28:55-08:00',\n\t\t\t\t'--replace=/stepsRequiredForRelease=[]',\n\t\t\t\t'--remove=/embargoed',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should update metadata object (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\t});\n\tleche.withData(\n\t\t['files:metadata:add', 'files:metadata:create'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet fileId = '1234567890',\n\t\t\t\t\tmetadataScope = 'enterprise',\n\t\t\t\t\tmetadataTemplate = 'testTemplate',\n\t\t\t\t\taddMetadataFixture = getFixture(\n\t\t\t\t\t\t'files/post_files_id_metadata_scope_template'\n\t\t\t\t\t),\n\t\t\t\t\tyamlOutput = getFixture(\n\t\t\t\t\t\t'output/files_metadata_create_yaml.txt'\n\t\t\t\t\t);\n\t\t\t\tlet createMetadataBody = {\n\t\t\t\t\ttest: 'test123',\n\t\t\t\t\tnumber: 1.9,\n\t\t\t\t\tarr: ['foo', 'bar'],\n\t\t\t\t};\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post(\n\t\t\t\t\t\t\t`/2.0/files/${fileId}/metadata/${metadataScope}/${metadataTemplate}`,\n\t\t\t\t\t\t\tcreateMetadataBody\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.reply(201, addMetadataFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tfileId,\n\t\t\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t\t\t'--data=test=test123',\n\t\t\t\t\t\t'--data=number=#1.9',\n\t\t\t\t\t\t'--data=arr=[foo,bar]',\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should add metadata object (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, addMetadataFixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post(\n\t\t\t\t\t\t\t`/2.0/files/${fileId}/metadata/${metadataScope}/${metadataTemplate}`,\n\t\t\t\t\t\t\tcreateMetadataBody\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.reply(201, addMetadataFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tfileId,\n\t\t\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t\t\t'--data=test=test123',\n\t\t\t\t\t\t'--data=number=#1.9',\n\t\t\t\t\t\t'--data=arr=[foo,bar]',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should add metadata object (YAML Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tdescribe('files:metadata:set', function () {\n\t\tlet fileID = '11111',\n\t\t\tmetadataScope = 'enterprise',\n\t\t\tmetadataTemplate = 'testTemplate',\n\t\t\taddMetadataFixture = getFixture(\n\t\t\t\t'files/post_files_id_metadata_scope_template'\n\t\t\t),\n\t\t\tyamlOutput = getFixture('output/files_metadata_create_yaml.txt');\n\t\tlet createMetadataBody = {\n\t\t\ttest: 'test123',\n\t\t\tnumber: 1.9,\n\t\t\tarr: ['foo', 'bar'],\n\t\t};\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(\n\t\t\t\t\t`/2.0/files/${fileID}/metadata/${metadataScope}/${metadataTemplate}`,\n\t\t\t\t\tcreateMetadataBody\n\t\t\t\t)\n\t\t\t\t.reply(201, addMetadataFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:metadata:set',\n\t\t\t\tfileID,\n\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t'--data=test=test123',\n\t\t\t\t'--data=number=#1.9',\n\t\t\t\t'--data=arr=[foo,bar]',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should add metadata object with key/value pairs passed as a flag (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, addMetadataFixture);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(\n\t\t\t\t\t`/2.0/files/${fileID}/metadata/${metadataScope}/${metadataTemplate}`,\n\t\t\t\t\tcreateMetadataBody\n\t\t\t\t)\n\t\t\t\t.reply(201, addMetadataFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:metadata:set',\n\t\t\t\tfileID,\n\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t'--data=test=test123',\n\t\t\t\t'--data=number=#1.9',\n\t\t\t\t'--data=arr=[foo,bar]',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should add metadata object with key/value pairs passed as a flag (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(\n\t\t\t\t\t`/2.0/files/${fileID}/metadata/${metadataScope}/${metadataTemplate}`,\n\t\t\t\t\tcreateMetadataBody\n\t\t\t\t)\n\t\t\t\t.reply(409)\n\t\t\t\t.put(\n\t\t\t\t\t`/2.0/files/${fileID}/metadata/${metadataScope}/${metadataTemplate}`,\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\top: 'add',\n\t\t\t\t\t\t\tpath: '/test',\n\t\t\t\t\t\t\tvalue: 'test123',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\top: 'add',\n\t\t\t\t\t\t\tpath: '/number',\n\t\t\t\t\t\t\tvalue: 1.9,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\top: 'add',\n\t\t\t\t\t\t\tpath: '/arr',\n\t\t\t\t\t\t\tvalue: ['foo', 'bar'],\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t)\n\t\t\t\t.reply(200, addMetadataFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:metadata:set',\n\t\t\t\tfileID,\n\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t'--data=test=test123',\n\t\t\t\t'--data=number=#1.9',\n\t\t\t\t'--data=arr=[foo,bar]',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update metadata object with key/value pairs passed as a flag when creation conflicts',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, addMetadataFixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\tleche.withData(\n\t\t[\n\t\t\t'files:share',\n\t\t\t'files:shared-links:create',\n\t\t\t'files:shared-links:update',\n\t\t],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet fileId = '1234567890',\n\t\t\t\t\tvanityName = 'my-custom-name-123',\n\t\t\t\t\tunsharedDate = '2030-11-18T19:44:17+00:00',\n\t\t\t\t\tcreateSharedLinkFixture = getFixture(\n\t\t\t\t\t\t'files/put_files_id_shared_link'\n\t\t\t\t\t),\n\t\t\t\t\tjsonOutput = getFixture('output/files_share_json.txt'),\n\t\t\t\t\tyamlOutput = getFixture('output/files_share_yaml.txt');\n\t\t\t\tlet sharedLinkBody = {\n\t\t\t\t\tshared_link: {\n\t\t\t\t\t\tpermissions: { can_download: true, can_edit: true },\n\t\t\t\t\t\taccess: 'test',\n\t\t\t\t\t\tpassword: 'test',\n\t\t\t\t\t\tvanity_name: vanityName,\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(\n\t\t\t\t\t\t\t`/2.0/files/${fileId}?fields=shared_link`,\n\t\t\t\t\t\t\tsharedLinkBody\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.reply(200, createSharedLinkFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tfileId,\n\t\t\t\t\t\t'--access=test',\n\t\t\t\t\t\t'--password=test',\n\t\t\t\t\t\t'--can-download',\n\t\t\t\t\t\t`--vanity-name=${vanityName}`,\n\t\t\t\t\t\t'--can-edit',\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should create a shared link for a Box item (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(\n\t\t\t\t\t\t\t`/2.0/files/${fileId}?fields=shared_link`,\n\t\t\t\t\t\t\tsharedLinkBody\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.reply(200, createSharedLinkFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tfileId,\n\t\t\t\t\t\t'--access=test',\n\t\t\t\t\t\t'--password=test',\n\t\t\t\t\t\t'--can-download',\n\t\t\t\t\t\t`--vanity-name=${vanityName}`,\n\t\t\t\t\t\t'--can-edit',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should create a shared link for a Box item (YAML Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(`/2.0/files/${fileId}?fields=shared_link`, {\n\t\t\t\t\t\t\tshared_link: {\n\t\t\t\t\t\t\t\tpermissions: {},\n\t\t\t\t\t\t\t\tunshared_at: unsharedDate,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, createSharedLinkFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tfileId,\n\t\t\t\t\t\t`--unshared-at=${unsharedDate}`,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should send unshared_at param when --unshared-at flag is passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(`/2.0/files/${fileId}?fields=shared_link`, {\n\t\t\t\t\t\t\tshared_link: {\n\t\t\t\t\t\t\t\tpermissions: {},\n\t\t\t\t\t\t\t\tunshared_at: unsharedDate,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, createSharedLinkFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\t`--unshared-at=${unsharedDate}`,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\tfileId,\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should work with args in non-standard order',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\tleche.withData(\n\t\t['files:unshare', 'files:shared-links:delete'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet fileId = '1234567809',\n\t\t\t\t\tgetFileFixture = getFixture('files/get_files_id');\n\t\t\t\tlet deleteSharedLinkBody = {\n\t\t\t\t\tshared_link: null,\n\t\t\t\t};\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(`/2.0/files/${fileId}`, deleteSharedLinkBody)\n\t\t\t\t\t\t.reply(200, getFileFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.stderr()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tfileId,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--no-color',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it('should delete a shared link for a file', (context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t\t`Removed shared link from file \"test_file_download.txt\"${os.EOL}`\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(`/2.0/files/${fileId}`, deleteSharedLinkBody)\n\t\t\t\t\t\t.reply(200, getFileFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.stderr()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--no-color',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t\tfileId,\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should work with args in non-standard order',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t\t\t`Removed shared link from file \"test_file_download.txt\"${os.EOL}`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\tleche.withData(['files:tasks', 'files:tasks:list'], function (command) {\n\t\tdescribe(command, function () {\n\t\t\tlet fileId = '1234567890',\n\t\t\t\tfixture = getFixture('files/get_files_id_tasks_page_1'),\n\t\t\t\tfixture2 = getFixture('files/get_files_id_tasks_page_2'),\n\t\t\t\tjsonOutput = getFixture('output/files_tasks_list_json.txt');\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get(`/2.0/files/${fileId}/tasks`)\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get(`/2.0/files/${fileId}/tasks`)\n\t\t\t\t\t.query({\n\t\t\t\t\t\toffset: 1,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([command, fileId, '--json', '--token=test'])\n\t\t\t\t.it(\n\t\t\t\t\t'should list all tasks on this file (JSON Output)',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get(`/2.0/files/${fileId}/tasks`)\n\t\t\t\t\t.query({ fields: 'id' })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get(`/2.0/files/${fileId}/tasks`)\n\t\t\t\t\t.query({\n\t\t\t\t\t\tfields: 'id',\n\t\t\t\t\t\toffset: 1,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\tfileId,\n\t\t\t\t\t'--fields=id',\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t\t);\n\t\t});\n\t});\n\tleche.withData(\n\t\t['files:versions', 'files:versions:list'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet fileId = '1234567890',\n\t\t\t\t\tfixture = getFixture('files/get_files_id_versions_page_1'),\n\t\t\t\t\tfixture2 = getFixture('files/get_files_id_versions_page_2'),\n\t\t\t\t\tjsonOutput = getFixture(\n\t\t\t\t\t\t'output/files_versions_list_json.txt'\n\t\t\t\t\t);\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/files/${fileId}/versions`)\n\t\t\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t.get(`/2.0/files/${fileId}/versions`)\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\toffset: 2,\n\t\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, fileId, '--json', '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should get a list of file versions (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/files/${fileId}/versions`)\n\t\t\t\t\t\t.query({ fields: 'sha1', limit: 1000 })\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t.get(`/2.0/files/${fileId}/versions`)\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\tfields: 'sha1',\n\t\t\t\t\t\t\toffset: 2,\n\t\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tfileId,\n\t\t\t\t\t\t'--fields=sha1',\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tdescribe('files:versions:delete', function () {\n\t\tlet fileId = '1234567890',\n\t\t\tversionId = '1234567890';\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.delete(`/2.0/files/${fileId}/versions/${versionId}`).reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:versions:delete',\n\t\t\t\tfileId,\n\t\t\t\tversionId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should delete a file version', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Deleted file version ${versionId} from file ${fileId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(`/2.0/files/${fileId}/versions/${versionId}`)\n\t\t\t\t.matchHeader('If-Match', '5')\n\t\t\t\t.reply(412, {\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\tstatus: 412,\n\t\t\t\t\tcode: 'precondition_failed',\n\t\t\t\t\thelp_url: 'http://developers.box.com/docs/#errors',\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t'The resource has been modified. Please retrieve the resource again and retry',\n\t\t\t\t\trequest_id: '1wne91fxf8871ide',\n\t\t\t\t})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:versions:delete',\n\t\t\t\tfileId,\n\t\t\t\tversionId,\n\t\t\t\t'--json',\n\t\t\t\t'--no-color',\n\t\t\t\t'--etag=5',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send If-Match header and throw error when etag flag is passed but does not match',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet message =\n\t\t\t\t\t\t'Unexpected API Response [412 Precondition Failed | 1wne91fxf8871ide] precondition_failed - The resource has been modified. Please retrieve the resource again and retry';\n\t\t\t\t\tassert.equal(context.stderr, `${message}${os.EOL}`);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('files:versions:promote', function () {\n\t\tlet fileId = '1234567890',\n\t\t\tversionId = '1234567890',\n\t\t\tpromoteVersionFixture = getFixture(\n\t\t\t\t'files/post_files_id_versions_current'\n\t\t\t),\n\t\t\tyamlOutput = getFixture('output/files_versions_promote_yaml.txt');\n\t\tlet promoteVersionBody = {\n\t\t\ttype: 'file_version',\n\t\t\tid: versionId,\n\t\t};\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(\n\t\t\t\t\t`/2.0/files/${fileId}/versions/current`,\n\t\t\t\t\tpromoteVersionBody\n\t\t\t\t)\n\t\t\t\t.reply(201, promoteVersionFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:versions:promote',\n\t\t\t\tfileId,\n\t\t\t\tversionId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should promote a file version (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, promoteVersionFixture);\n\t\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(\n\t\t\t\t\t`/2.0/files/${fileId}/versions/current`,\n\t\t\t\t\tpromoteVersionBody\n\t\t\t\t)\n\t\t\t\t.reply(201, promoteVersionFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:versions:promote',\n\t\t\t\tfileId,\n\t\t\t\tversionId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should promote a file version (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\t});\n\n\tdescribe('files:update', function () {\n\t\tlet fileID = '55555',\n\t\t\tname = 'Document v1.pdf',\n\t\t\tdescription = 'New description',\n\t\t\ttags = 'foo,bar',\n\t\t\tfixture = getFixture('files/put_files_id'),\n\t\t\tyamlOutput = getFixture('output/files_rename_yaml.txt'),\n\t\t\tdispositionAt = '2025-12-09T04:07:18-08:00';\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.put(`/2.0/files/${fileID}`, { name }).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:update',\n\t\t\t\tfileID,\n\t\t\t\t`--name=${name}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a file with name flag passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.put(`/2.0/files/${fileID}`, { name }).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['files:update', fileID, `--name=${name}`, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should update a file with name flag passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/files/${fileID}`, {\n\t\t\t\t\tname,\n\t\t\t\t\tdescription,\n\t\t\t\t\ttags: tags.split(','),\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:update',\n\t\t\t\tfileID,\n\t\t\t\t`--name=${name}`,\n\t\t\t\t`--description=${description}`,\n\t\t\t\t`--tags=${tags}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send optional params when flags are passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/files/${fileID}`, { name })\n\t\t\t\t.matchHeader('If-Match', '5')\n\t\t\t\t.reply(412, {\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\tstatus: 412,\n\t\t\t\t\tcode: 'precondition_failed',\n\t\t\t\t\thelp_url: 'http://developers.box.com/docs/#errors',\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t'The resource has been modified. Please retrieve the resource again and retry',\n\t\t\t\t\trequest_id: '1wne91fxf8871ide',\n\t\t\t\t})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:update',\n\t\t\t\tfileID,\n\t\t\t\t`--name=${name}`,\n\t\t\t\t'--no-color',\n\t\t\t\t'--etag=5',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send If-Match header and throw error when etag flag is passed but does not match',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet message =\n\t\t\t\t\t\t'Unexpected API Response [412 Precondition Failed | 1wne91fxf8871ide] precondition_failed - The resource has been modified. Please retrieve the resource again and retry';\n\t\t\t\t\tassert.equal(context.stderr, `${message}${os.EOL}`);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/files/${fileID}`, {\n\t\t\t\t\tdisposition_at: dispositionAt,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:update',\n\t\t\t\tfileID,\n\t\t\t\t`--disposition-at=${dispositionAt}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('shoud update disposition_at property of a file', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\t});\n\n\tdescribe('files:versions:upload', function () {\n\t\tlet fileId = '1234567890',\n\t\t\ttestFileName = 'test_file.txt',\n\t\t\ttestFileContent = 'hello',\n\t\t\tcontentModifiedAt = '2012-12-20T20:20:12+00:00',\n\t\t\ttestFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'..',\n\t\t\t\t`fixtures/files/${testFileName}`\n\t\t\t),\n\t\t\tuploadFileFixture = getFixture('files/post_files_content'),\n\t\t\tjsonOutput = getFixture('output/files_versions_upload_json.txt'),\n\t\t\tyamlOutput = getFixture('output/files_versions_upload_yaml.txt');\n\t\ttest.nock(TEST_UPLOAD_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/files/${fileId}/content`, function (body) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlet lines = body.split(/\\r?\\n/u);\n\t\t\t\t\t\tassert.match(lines[0], /^-+[a-f0-9]+$/u);\n\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\tlines[1],\n\t\t\t\t\t\t\t'Content-Disposition: form-data; name=\"attributes\"'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.equal(lines[2], '');\n\t\t\t\t\t\tlet attributes = JSON.parse(lines[3]);\n\t\t\t\t\t\tassert.propertyVal(attributes, 'name', testFileName);\n\t\t\t\t\t\tassert.match(lines[4], /^-+[a-f0-9]+$/u);\n\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\tlines[5],\n\t\t\t\t\t\t\t'Content-Disposition: form-data; name=\"content\"; filename=\"unused\"'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.equal(lines[6], 'Content-Type: text/plain');\n\t\t\t\t\t\tassert.equal(lines[7], '');\n\t\t\t\t\t\tassert.equal(lines[8], testFileContent);\n\t\t\t\t\t\tassert.match(lines[9], /^-+[a-f0-9]+-+$/u);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.reply(201, uploadFileFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:versions:upload',\n\t\t\t\tfileId,\n\t\t\t\ttestFilePath,\n\t\t\t\t`--name=${testFileName}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should upload a new version of a file (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_UPLOAD_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/files/${fileId}/content`, function (body) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlet lines = body.split(/\\r?\\n/u);\n\t\t\t\t\t\tassert.match(lines[0], /^-+[a-f0-9]+$/u);\n\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\tlines[1],\n\t\t\t\t\t\t\t'Content-Disposition: form-data; name=\"attributes\"'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.equal(lines[2], '');\n\t\t\t\t\t\tlet attributes = JSON.parse(lines[3]);\n\t\t\t\t\t\tassert.propertyVal(attributes, 'name', testFileName);\n\t\t\t\t\t\tassert.match(lines[4], /^-+[a-f0-9]+$/u);\n\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\tlines[5],\n\t\t\t\t\t\t\t'Content-Disposition: form-data; name=\"content\"; filename=\"unused\"'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.equal(lines[6], 'Content-Type: text/plain');\n\t\t\t\t\t\tassert.equal(lines[7], '');\n\t\t\t\t\t\tassert.equal(lines[8], testFileContent);\n\t\t\t\t\t\tassert.match(lines[9], /^-+[a-f0-9]+-+$/u);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.reply(201, uploadFileFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:versions:upload',\n\t\t\t\tfileId,\n\t\t\t\ttestFilePath,\n\t\t\t\t`--name=${testFileName}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should upload a new version of a file (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_UPLOAD_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/files/${fileId}/content`, function (body) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlet lines = body.split(/\\r?\\n/u);\n\t\t\t\t\t\tlet attributes = JSON.parse(lines[3]);\n\t\t\t\t\t\tassert.propertyVal(\n\t\t\t\t\t\t\tattributes,\n\t\t\t\t\t\t\t'content_modified_at',\n\t\t\t\t\t\t\tcontentModifiedAt\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.equal(lines[8], testFileContent);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.reply(201, uploadFileFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:versions:upload',\n\t\t\t\tfileId,\n\t\t\t\ttestFilePath,\n\t\t\t\t`--content-modified-at=${contentModifiedAt}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should upload file with content timestamp when --content-modified-at flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('files:upload', function () {\n\t\tlet parentFolderId = '987654321',\n\t\t\ttestFileName = 'test_file.txt',\n\t\t\tnewFileName = 'renamed_file.txt',\n\t\t\ttestFileContent = 'hello',\n\t\t\tcontentCreatedAt = '2017-02-03T12:34:56+00:00',\n\t\t\tcontentModifiedAt = '2017-11-18T09:12:44+00:00',\n\t\t\ttestFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'..',\n\t\t\t\t`fixtures/files/${testFileName}`\n\t\t\t),\n\t\t\tuploadFileFixture = getFixture('files/post_files_content'),\n\t\t\tjsonOutput = getFixture('output/files_upload_json.txt'),\n\t\t\tyamlOutput = getFixture('output/files_upload_yaml.txt');\n\t\ttest.nock(TEST_UPLOAD_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/files/content', function (body) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlet lines = body.split(/\\r?\\n/u);\n\t\t\t\t\t\tlet attributes = JSON.parse(lines[3]);\n\t\t\t\t\t\tassert.propertyVal(attributes, 'name', testFileName);\n\t\t\t\t\t\tassert.nestedPropertyVal(\n\t\t\t\t\t\t\tattributes,\n\t\t\t\t\t\t\t'parent.id',\n\t\t\t\t\t\t\tparentFolderId\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.equal(lines[8], testFileContent);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.reply(201, uploadFileFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:upload',\n\t\t\t\ttestFilePath,\n\t\t\t\t`--parent-id=${parentFolderId}`,\n\t\t\t\t`--name=${testFileName}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should upload a file (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t});\n\t\ttest.nock(TEST_UPLOAD_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/files/content', function (body) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlet lines = body.split(/\\r?\\n/u);\n\t\t\t\t\t\tlet attributes = JSON.parse(lines[3]);\n\t\t\t\t\t\tassert.propertyVal(attributes, 'name', testFileName);\n\t\t\t\t\t\tassert.nestedPropertyVal(\n\t\t\t\t\t\t\tattributes,\n\t\t\t\t\t\t\t'parent.id',\n\t\t\t\t\t\t\tparentFolderId\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.equal(lines[8], testFileContent);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.reply(201, uploadFileFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:upload',\n\t\t\t\ttestFilePath,\n\t\t\t\t`--parent-id=${parentFolderId}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should upload a file (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\t\ttest.nock(TEST_UPLOAD_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/files/content', function (body) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlet lines = body.split(/\\r?\\n/u);\n\t\t\t\t\t\tlet attributes = JSON.parse(lines[3]);\n\t\t\t\t\t\tassert.propertyVal(attributes, 'name', testFileName);\n\t\t\t\t\t\tassert.nestedPropertyVal(\n\t\t\t\t\t\t\tattributes,\n\t\t\t\t\t\t\t'parent.id',\n\t\t\t\t\t\t\tparentFolderId\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.equal(lines[8], testFileContent);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.reply(201, uploadFileFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:upload',\n\t\t\t\ttestFilePath,\n\t\t\t\t`--parent-id=${parentFolderId}`,\n\t\t\t\t'--id-only',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should output only the ID of the new file when --id-only flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\tJSON.parse(uploadFileFixture).entries[0].id\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_UPLOAD_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/files/content', function (body) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlet lines = body.split(/\\r?\\n/u);\n\t\t\t\t\t\tlet attributes = JSON.parse(lines[3]);\n\t\t\t\t\t\tassert.propertyVal(attributes, 'name', newFileName);\n\t\t\t\t\t\tassert.nestedPropertyVal(\n\t\t\t\t\t\t\tattributes,\n\t\t\t\t\t\t\t'parent.id',\n\t\t\t\t\t\t\tparentFolderId\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.equal(lines[8], testFileContent);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.reply(201, uploadFileFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:upload',\n\t\t\t\ttestFilePath,\n\t\t\t\t`--parent-id=${parentFolderId}`,\n\t\t\t\t`--name=${newFileName}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should upload file with new name when --name flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_UPLOAD_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/files/content', function (body) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tlet lines = body.split(/\\r?\\n/u);\n\t\t\t\t\t\tlet attributes = JSON.parse(lines[3]);\n\t\t\t\t\t\tassert.propertyVal(\n\t\t\t\t\t\t\tattributes,\n\t\t\t\t\t\t\t'content_created_at',\n\t\t\t\t\t\t\tcontentCreatedAt\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.propertyVal(\n\t\t\t\t\t\t\tattributes,\n\t\t\t\t\t\t\t'content_modified_at',\n\t\t\t\t\t\t\tcontentModifiedAt\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.nestedPropertyVal(\n\t\t\t\t\t\t\tattributes,\n\t\t\t\t\t\t\t'parent.id',\n\t\t\t\t\t\t\tparentFolderId\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.equal(lines[8], testFileContent);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.reply(201, uploadFileFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:upload',\n\t\t\t\ttestFilePath,\n\t\t\t\t`--parent-id=${parentFolderId}`,\n\t\t\t\t`--content-created-at=${contentCreatedAt}`,\n\t\t\t\t`--content-modified-at=${contentModifiedAt}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should upload file with content timestamps when --content-*-at flags are passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\t\tlet existingFileId = '55555',\n\t\t\tconflictError = {\n\t\t\t\ttype: 'error',\n\t\t\t\tstatus: 409,\n\t\t\t\tcode: 'item_name_in_use',\n\t\t\t\thelp_url: 'http://developers.box.com/docs/#errors',\n\t\t\t\tmessage: 'Item with the same name already exists',\n\t\t\t\trequest_id: 'abc123',\n\t\t\t\tcontext_info: {\n\t\t\t\t\tconflicts: {\n\t\t\t\t\t\ttype: 'file',\n\t\t\t\t\t\tid: existingFileId,\n\t\t\t\t\t\tname: testFileName,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\ttest.nock(TEST_UPLOAD_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/files/content')\n\t\t\t\t.reply(409, conflictError)\n\t\t\t\t.post(`/2.0/files/${existingFileId}/content`)\n\t\t\t\t.reply(201, uploadFileFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:upload',\n\t\t\t\ttestFilePath,\n\t\t\t\t`--parent-id=${parentFolderId}`,\n\t\t\t\t'--overwrite',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should upload a new version when --overwrite flag is passed and file already exists',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_UPLOAD_ROOT, (api) =>\n\t\t\tapi.post('/2.0/files/content').reply(409, conflictError)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:upload',\n\t\t\t\ttestFilePath,\n\t\t\t\t`--parent-id=${parentFolderId}`,\n\t\t\t\t'--json',\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should propagate 409 error when --overwrite flag is not passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t'A file with the same name already exists in the destination folder. Use --overwrite to replace it with a new version.'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_UPLOAD_ROOT, (api) =>\n\t\t\tapi.post('/2.0/files/content').reply(403, {\n\t\t\t\ttype: 'error',\n\t\t\t\tstatus: 403,\n\t\t\t\tcode: 'unauthorized',\n\t\t\t\thelp_url: 'http://developers.box.com/docs/#errors',\n\t\t\t\tmessage: 'Access denied',\n\t\t\t})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:upload',\n\t\t\t\ttestFilePath,\n\t\t\t\t`--parent-id=${parentFolderId}`,\n\t\t\t\t'--overwrite',\n\t\t\t\t'--json',\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should propagate non 409 errors even when --overwrite flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.include(context.stderr, '403');\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('files:download', function () {\n\t\tlet fileId = '12345',\n\t\t\tfileName = 'test_file_download.txt',\n\t\t\tsaveAsFileName = 'new_file_name.txt',\n\t\t\tfileVersionID = '8764569',\n\t\t\ttestFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'..',\n\t\t\t\t'fixtures/files/epic-poem.txt'\n\t\t\t),\n\t\t\ttestFileStat = fs.statSync(testFilePath),\n\t\t\tfileDownloadPath = path.join(__dirname, '..', 'fixtures/files'),\n\t\t\tfileDownloadUrl = toUrlPath(fileDownloadPath),\n\t\t\ttemporaryDestinationPath = path.join(fileDownloadPath, 'filesTemp'),\n\t\t\ttemporaryDestinationPath2 = path.join(\n\t\t\t\tfileDownloadPath,\n\t\t\t\t'filesTemp2'\n\t\t\t),\n\t\t\tgetFileFixture = getFixture('files/get_files_id'),\n\t\t\ttestFileInfo = JSON.parse(getFileFixture);\n\t\ttestFileInfo.size = testFileStat.size;\n\n\t\tafter(function () {\n\t\t\tfs.rmdirSync(temporaryDestinationPath);\n\t\t\tfs.rmdirSync(temporaryDestinationPath2);\n\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/files/${fileId}`)\n\t\t\t\t.reply(200, JSON.stringify(testFileInfo))\n\t\t\t\t.get(`/2.0/files/${fileId}/content`)\n\t\t\t\t.reply(302, '', {\n\t\t\t\t\tLocation: TEST_DOWNLOAD_ROOT + fileDownloadUrl,\n\t\t\t\t})\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get(fileDownloadUrl).reply(200, function () {\n\t\t\t\t\treturn fs.createReadStream(testFilePath, 'utf8');\n\t\t\t\t})\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:download',\n\t\t\t\tfileId,\n\t\t\t\t`--destination=${fileDownloadPath}`,\n\t\t\t\t'-y',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should download a file', (context) => {\n\t\t\t\tlet downloadedFilePath = path.join(fileDownloadPath, fileName);\n\t\t\t\tlet downloadContent = fs.readFileSync(downloadedFilePath);\n\t\t\t\tlet expectedContent = fs.readFileSync(testFilePath);\n\t\t\t\tlet downloadedFileStat = fs.statSync(downloadedFilePath);\n\t\t\t\tassert.equal(testFileStat.size, downloadedFileStat.size);\n\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\tassert.ok(downloadContent.equals(expectedContent));\n\t\t\t\tlet expectedMessage = getDownloadProgressBar(testFileStat.size);\n\t\t\t\texpectedMessage += `Downloaded file test_file_download.txt${os.EOL}`;\n\t\t\t\tassert.equal(context.stderr, expectedMessage);\n\t\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/files/${fileId}`)\n\t\t\t\t.reply(200, getFileFixture)\n\t\t\t\t.get(`/2.0/files/${fileId}/content`)\n\t\t\t\t.reply(302, '', {\n\t\t\t\t\tLocation: TEST_DOWNLOAD_ROOT + fileDownloadUrl,\n\t\t\t\t})\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get(fileDownloadUrl).reply(200, function () {\n\t\t\t\t\treturn fs.createReadStream(testFilePath, 'utf8');\n\t\t\t\t})\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:download',\n\t\t\t\tfileId,\n\t\t\t\t`--destination=${temporaryDestinationPath}`,\n\t\t\t\t'-y',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should download a file to a non-existing destination', () => {\n\t\t\t\tlet downloadedFilePath = path.join(\n\t\t\t\t\ttemporaryDestinationPath,\n\t\t\t\t\tfileName\n\t\t\t\t);\n\t\t\t\tlet downloadContent = fs.readFileSync(downloadedFilePath);\n\t\t\t\tlet expectedContent = fs.readFileSync(testFilePath);\n\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\tassert.ok(downloadContent.equals(expectedContent));\n\t\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/files/${fileId}`)\n\t\t\t\t.reply(200, getFileFixture)\n\t\t\t\t.get(`/2.0/files/${fileId}/content`)\n\t\t\t\t.reply(302, '', {\n\t\t\t\t\tLocation: TEST_DOWNLOAD_ROOT + fileDownloadUrl,\n\t\t\t\t})\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get(fileDownloadUrl).reply(200, function () {\n\t\t\t\t\treturn fs.createReadStream(testFilePath, 'utf8');\n\t\t\t\t})\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command(['files:download', fileId, '-y', '--token=test'])\n\t\t\t.it('should download a file to a default destination', () => {\n\t\t\t\tlet downloadedFilePath = path.join(\n\t\t\t\t\tDEFAULT_DOWNLOAD_PATH,\n\t\t\t\t\tfileName\n\t\t\t\t);\n\t\t\t\tlet downloadContent = fs.readFileSync(downloadedFilePath);\n\t\t\t\tlet expectedContent = fs.readFileSync(testFilePath);\n\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\tassert.ok(downloadContent.equals(expectedContent));\n\t\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/files/${fileId}`)\n\t\t\t\t.reply(200, getFileFixture)\n\t\t\t\t.get(`/2.0/files/${fileId}/content`)\n\t\t\t\t.reply(302, '', {\n\t\t\t\t\tLocation: TEST_DOWNLOAD_ROOT + fileDownloadUrl,\n\t\t\t\t})\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get(fileDownloadUrl).reply(200, function () {\n\t\t\t\t\treturn fs.createReadStream(testFilePath, 'utf8');\n\t\t\t\t})\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:download',\n\t\t\t\tfileId,\n\t\t\t\t`--save-as=${saveAsFileName}`,\n\t\t\t\t`--destination=${temporaryDestinationPath2}`,\n\t\t\t\t'-y',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should save downloaded file using provided filename in save-as parameter',\n\t\t\t\t() => {\n\t\t\t\t\tlet downloadedFilePath = path.join(\n\t\t\t\t\t\ttemporaryDestinationPath2,\n\t\t\t\t\t\tsaveAsFileName\n\t\t\t\t\t);\n\t\t\t\t\tlet downloadContent = fs.readFileSync(downloadedFilePath);\n\t\t\t\t\tlet expectedContent = fs.readFileSync(testFilePath);\n\t\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\t\tassert.ok(downloadContent.equals(expectedContent));\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/files/${fileId}`)\n\t\t\t\t.reply(200, getFileFixture)\n\t\t\t\t.get(`/2.0/files/${fileId}/content`)\n\t\t\t\t.reply(302, '', {\n\t\t\t\t\tLocation: TEST_DOWNLOAD_ROOT + fileDownloadUrl,\n\t\t\t\t})\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get(fileDownloadUrl).reply(200, function () {\n\t\t\t\t\treturn fs.createReadStream(testFilePath, 'utf8');\n\t\t\t\t})\n\t\t\t)\n\t\t\t.do(() => {\n\t\t\t\tfs.writeFileSync(\n\t\t\t\t\tpath.join(DEFAULT_DOWNLOAD_PATH, saveAsFileName),\n\t\t\t\t\t'foo',\n\t\t\t\t\t'utf8'\n\t\t\t\t);\n\t\t\t})\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:download',\n\t\t\t\tfileId,\n\t\t\t\t`--save-as=${saveAsFileName}`,\n\t\t\t\t'--overwrite',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should overwrite downloaded file when --overwrite flag is used',\n\t\t\t\t() => {\n\t\t\t\t\tlet downloadedFilePath = path.join(\n\t\t\t\t\t\tDEFAULT_DOWNLOAD_PATH,\n\t\t\t\t\t\tsaveAsFileName\n\t\t\t\t\t);\n\t\t\t\t\tlet downloadContent = fs.readFileSync(downloadedFilePath);\n\t\t\t\t\tlet expectedContent = fs.readFileSync(testFilePath);\n\t\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\t\tassert.ok(downloadContent.equals(expectedContent));\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/files/${fileId}`).reply(200, getFileFixture)\n\t\t)\n\t\t\t.do(() => {\n\t\t\t\tfs.writeFileSync(\n\t\t\t\t\tpath.join(DEFAULT_DOWNLOAD_PATH, saveAsFileName),\n\t\t\t\t\t'foo',\n\t\t\t\t\t'utf8'\n\t\t\t\t);\n\t\t\t})\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:download',\n\t\t\t\tfileId,\n\t\t\t\t`--save-as=${saveAsFileName}`,\n\t\t\t\t'--no-overwrite',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should skip downloading when file exists and --no-overwrite flag is used',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet downloadedFilePath = path.join(\n\t\t\t\t\t\tDEFAULT_DOWNLOAD_PATH,\n\t\t\t\t\t\tsaveAsFileName\n\t\t\t\t\t);\n\t\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Downloading the file will not occur because the file ${downloadedFilePath} already exists, and the --no-overwrite flag is set.${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/files/${fileId}`)\n\t\t\t\t.reply(200, JSON.stringify(testFileInfo))\n\t\t\t\t.get(`/2.0/files/${fileId}/content`)\n\t\t\t\t.query({ version: fileVersionID })\n\t\t\t\t.reply(302, '', {\n\t\t\t\t\tLocation: TEST_DOWNLOAD_ROOT + fileDownloadUrl,\n\t\t\t\t})\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get(fileDownloadUrl).reply(200, function () {\n\t\t\t\t\treturn fs.createReadStream(testFilePath, 'utf8');\n\t\t\t\t})\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:download',\n\t\t\t\tfileId,\n\t\t\t\t`--destination=${fileDownloadPath}`,\n\t\t\t\t`--version=${fileVersionID}`,\n\t\t\t\t'-y',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should download a file version when version flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet downloadedFilePath = path.join(\n\t\t\t\t\t\tfileDownloadPath,\n\t\t\t\t\t\tfileName\n\t\t\t\t\t);\n\t\t\t\t\tlet downloadContent = fs.readFileSync(downloadedFilePath);\n\t\t\t\t\tlet expectedContent = fs.readFileSync(testFilePath);\n\t\t\t\t\tlet downloadedFileStat = fs.statSync(downloadedFilePath);\n\t\t\t\t\tassert.equal(testFileStat.size, downloadedFileStat.size);\n\t\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\t\tassert.ok(downloadContent.equals(expectedContent));\n\t\t\t\t\tlet expectedMessage = getDownloadProgressBar(\n\t\t\t\t\t\ttestFileStat.size\n\t\t\t\t\t);\n\t\t\t\t\texpectedMessage += `Downloaded file test_file_download.txt${os.EOL}`;\n\t\t\t\t\tassert.equal(context.stderr, expectedMessage);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('files:versions:download', function () {\n\t\tlet fileId = '12345',\n\t\t\tfileName = 'test_file_download.txt',\n\t\t\tsaveAsFileName = 'new_file_name.txt',\n\t\t\tfileVersionID = '8764569',\n\t\t\ttestFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'..',\n\t\t\t\t'fixtures/files/epic-poem.txt'\n\t\t\t),\n\t\t\tfileDownloadPath = path.join(__dirname, '..', 'fixtures/files'),\n\t\t\tfileDownloadUrl = toUrlPath(fileDownloadPath),\n\t\t\ttemporaryDestinationPath = path.join(\n\t\t\t\tfileDownloadPath,\n\t\t\t\t'versionsTemp'\n\t\t\t),\n\t\t\ttemporaryDestinationPath2 = path.join(\n\t\t\t\tfileDownloadPath,\n\t\t\t\t'versionsTemp2'\n\t\t\t),\n\t\t\tgetFileFixture = getFixture('files/get_files_id');\n\n\t\tafter(function () {\n\t\t\tfs.rmdirSync(temporaryDestinationPath);\n\t\t\tfs.rmdirSync(temporaryDestinationPath2);\n\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/files/${fileId}`)\n\t\t\t\t.reply(200, getFileFixture)\n\t\t\t\t.get(`/2.0/files/${fileId}/content`)\n\t\t\t\t.query({ version: fileVersionID })\n\t\t\t\t.reply(302, '', {\n\t\t\t\t\tLocation: TEST_DOWNLOAD_ROOT + fileDownloadUrl,\n\t\t\t\t})\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get(fileDownloadUrl).reply(200, function () {\n\t\t\t\t\treturn fs.createReadStream(testFilePath, 'utf8');\n\t\t\t\t})\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:versions:download',\n\t\t\t\tfileId,\n\t\t\t\tfileVersionID,\n\t\t\t\t`--destination=${fileDownloadPath}`,\n\t\t\t\t'-y',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should download a file version ', (context) => {\n\t\t\t\tlet downloadedFilePath = path.join(fileDownloadPath, fileName);\n\t\t\t\tlet downloadContent = fs.readFileSync(downloadedFilePath);\n\t\t\t\tlet expectedContent = fs.readFileSync(testFilePath);\n\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\tassert.ok(downloadContent.equals(expectedContent));\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Downloaded file test_file_download.txt${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/files/${fileId}`)\n\t\t\t\t.reply(200, getFileFixture)\n\t\t\t\t.get(`/2.0/files/${fileId}/content`)\n\t\t\t\t.query({ version: fileVersionID })\n\t\t\t\t.reply(302, '', {\n\t\t\t\t\tLocation: TEST_DOWNLOAD_ROOT + fileDownloadUrl,\n\t\t\t\t})\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get(fileDownloadUrl).reply(200, function () {\n\t\t\t\t\treturn fs.createReadStream(testFilePath, 'utf8');\n\t\t\t\t})\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:versions:download',\n\t\t\t\tfileId,\n\t\t\t\t`--destination=${fileDownloadPath}`,\n\t\t\t\t'-y',\n\t\t\t\tfileVersionID,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should work with arguments in non-standard order',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet downloadedFilePath = path.join(\n\t\t\t\t\t\tfileDownloadPath,\n\t\t\t\t\t\tfileName\n\t\t\t\t\t);\n\t\t\t\t\tlet downloadContent = fs.readFileSync(downloadedFilePath);\n\t\t\t\t\tlet expectedContent = fs.readFileSync(testFilePath);\n\t\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\t\tassert.ok(downloadContent.equals(expectedContent));\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Downloaded file test_file_download.txt${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/files/${fileId}`)\n\t\t\t\t.reply(200, getFileFixture)\n\t\t\t\t.get(`/2.0/files/${fileId}/content`)\n\t\t\t\t.query({ version: fileVersionID })\n\t\t\t\t.reply(302, '', {\n\t\t\t\t\tLocation: TEST_DOWNLOAD_ROOT + fileDownloadUrl,\n\t\t\t\t})\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get(fileDownloadUrl).reply(200, function () {\n\t\t\t\t\treturn fs.createReadStream(testFilePath, 'utf8');\n\t\t\t\t})\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:versions:download',\n\t\t\t\tfileId,\n\t\t\t\t'-y',\n\t\t\t\tfileVersionID,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should download a file version to a default destination',\n\t\t\t\t() => {\n\t\t\t\t\tlet downloadedFilePath = path.join(\n\t\t\t\t\t\tDEFAULT_DOWNLOAD_PATH,\n\t\t\t\t\t\tfileName\n\t\t\t\t\t);\n\t\t\t\t\tlet downloadContent = fs.readFileSync(downloadedFilePath);\n\t\t\t\t\tlet expectedContent = fs.readFileSync(testFilePath);\n\t\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\t\tassert.ok(downloadContent.equals(expectedContent));\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/files/${fileId}`)\n\t\t\t\t.reply(200, getFileFixture)\n\t\t\t\t.get(`/2.0/files/${fileId}/content`)\n\t\t\t\t.query({ version: fileVersionID })\n\t\t\t\t.reply(302, '', {\n\t\t\t\t\tLocation: TEST_DOWNLOAD_ROOT + fileDownloadUrl,\n\t\t\t\t})\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get(fileDownloadUrl).reply(200, function () {\n\t\t\t\t\treturn fs.createReadStream(testFilePath, 'utf8');\n\t\t\t\t})\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:versions:download',\n\t\t\t\tfileId,\n\t\t\t\t`--destination=${temporaryDestinationPath}`,\n\t\t\t\t'-y',\n\t\t\t\tfileVersionID,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should download a file version to a non-existing destination',\n\t\t\t\t() => {\n\t\t\t\t\tlet downloadedFilePath = path.join(\n\t\t\t\t\t\ttemporaryDestinationPath,\n\t\t\t\t\t\tfileName\n\t\t\t\t\t);\n\t\t\t\t\tlet downloadContent = fs.readFileSync(downloadedFilePath);\n\t\t\t\t\tlet expectedContent = fs.readFileSync(testFilePath);\n\t\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\t\tassert.ok(downloadContent.equals(expectedContent));\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/files/${fileId}`)\n\t\t\t\t.reply(200, getFileFixture)\n\t\t\t\t.get(`/2.0/files/${fileId}/content`)\n\t\t\t\t.query({ version: fileVersionID })\n\t\t\t\t.reply(302, '', {\n\t\t\t\t\tLocation: TEST_DOWNLOAD_ROOT + fileDownloadUrl,\n\t\t\t\t})\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get(fileDownloadUrl).reply(200, function () {\n\t\t\t\t\treturn fs.createReadStream(testFilePath, 'utf8');\n\t\t\t\t})\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:versions:download',\n\t\t\t\tfileId,\n\t\t\t\t`--save-as=${saveAsFileName}`,\n\t\t\t\t`--destination=${temporaryDestinationPath2}`,\n\t\t\t\t'-y',\n\t\t\t\tfileVersionID,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should save downloaded file version using provided filename in save-as parameter',\n\t\t\t\t() => {\n\t\t\t\t\tlet downloadedFilePath = path.join(\n\t\t\t\t\t\ttemporaryDestinationPath2,\n\t\t\t\t\t\tsaveAsFileName\n\t\t\t\t\t);\n\t\t\t\t\tlet downloadContent = fs.readFileSync(downloadedFilePath);\n\t\t\t\t\tlet expectedContent = fs.readFileSync(testFilePath);\n\t\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\t\tassert.ok(downloadContent.equals(expectedContent));\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/files/${fileId}`)\n\t\t\t\t.reply(200, getFileFixture)\n\t\t\t\t.get(`/2.0/files/${fileId}/content`)\n\t\t\t\t.query({ version: fileVersionID })\n\t\t\t\t.reply(302, '', {\n\t\t\t\t\tLocation: TEST_DOWNLOAD_ROOT + fileDownloadUrl,\n\t\t\t\t})\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get(fileDownloadUrl).reply(200, function () {\n\t\t\t\t\treturn fs.createReadStream(testFilePath, 'utf8');\n\t\t\t\t})\n\t\t\t)\n\t\t\t.do(() => {\n\t\t\t\tfs.writeFileSync(\n\t\t\t\t\tpath.join(DEFAULT_DOWNLOAD_PATH, saveAsFileName),\n\t\t\t\t\t'foo',\n\t\t\t\t\t'utf8'\n\t\t\t\t);\n\t\t\t})\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:versions:download',\n\t\t\t\tfileId,\n\t\t\t\t`--save-as=${saveAsFileName}`,\n\t\t\t\t'--overwrite',\n\t\t\t\tfileVersionID,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should overwrite downloaded file version when --overwrite flag is used',\n\t\t\t\t() => {\n\t\t\t\t\tlet downloadedFilePath = path.join(\n\t\t\t\t\t\tDEFAULT_DOWNLOAD_PATH,\n\t\t\t\t\t\tsaveAsFileName\n\t\t\t\t\t);\n\t\t\t\t\tlet downloadContent = fs.readFileSync(downloadedFilePath);\n\t\t\t\t\tlet expectedContent = fs.readFileSync(testFilePath);\n\t\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\t\tassert.ok(downloadContent.equals(expectedContent));\n\t\t\t\t}\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/files/${fileId}`).reply(200, getFileFixture)\n\t\t)\n\t\t\t.do(() => {\n\t\t\t\tfs.writeFileSync(\n\t\t\t\t\tpath.join(DEFAULT_DOWNLOAD_PATH, saveAsFileName),\n\t\t\t\t\t'foo',\n\t\t\t\t\t'utf8'\n\t\t\t\t);\n\t\t\t})\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:versions:download',\n\t\t\t\tfileId,\n\t\t\t\tfileVersionID,\n\t\t\t\t`--save-as=${saveAsFileName}`,\n\t\t\t\t'--no-overwrite',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should skip downloading when file exists and --no-overwrite flag is used',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet downloadedFilePath = path.join(\n\t\t\t\t\t\tDEFAULT_DOWNLOAD_PATH,\n\t\t\t\t\t\tsaveAsFileName\n\t\t\t\t\t);\n\t\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Downloading the file will not occur because the file ${downloadedFilePath} already exists, and the --no-overwrite flag is set.${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('files:zip', function () {\n\t\tlet fileName = 'test.zip',\n\t\t\titems = [\n\t\t\t\t{\n\t\t\t\t\ttype: 'file',\n\t\t\t\t\tid: '466239504569',\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\ttype: 'folder',\n\t\t\t\t\tid: '466239504580',\n\t\t\t\t},\n\t\t\t],\n\t\t\ttestFilePath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'..',\n\t\t\t\t'fixtures/files/test_file.txt'\n\t\t\t),\n\t\t\tfileDownloadPath = path.join(__dirname, '..', 'fixtures/files'),\n\t\t\texpectedBody = {\n\t\t\t\titems,\n\t\t\t\tdownload_file_name: fileName,\n\t\t\t},\n\t\t\tdownloadUrl = '/2.0/zip_downloads/124hfiowk3fa8kmrwh/content',\n\t\t\tstatusUrl = '/2.0/zip_downloads/124hfiowk3fa8kmrwh/status',\n\t\t\tcreateFileFixture = getFixture('files/post_zip_downloads'),\n\t\t\tdownloadStatusFixture = getFixture(\n\t\t\t\t'files/get_zip_downloads_status'\n\t\t\t);\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/zip_downloads', expectedBody)\n\t\t\t\t.reply(202, createFileFixture)\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get(downloadUrl).reply(200, function () {\n\t\t\t\t\treturn fs.createReadStream(testFilePath, 'utf8');\n\t\t\t\t})\n\t\t\t)\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi.get(statusUrl).reply(200, downloadStatusFixture)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:zip',\n\t\t\t\tfileName,\n\t\t\t\t`--item=${items[0].type}:${items[0].id}`,\n\t\t\t\t`--item=${items[1].type}:${items[1].id}`,\n\t\t\t\t`--destination=${fileDownloadPath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a zip of multiple files and folders and download it',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet downloadedFilePath = path.join(\n\t\t\t\t\t\tfileDownloadPath,\n\t\t\t\t\t\tfileName\n\t\t\t\t\t);\n\t\t\t\t\tlet downloadContent = fs.readFileSync(downloadedFilePath);\n\t\t\t\t\tlet expectedContent = fs.readFileSync(testFilePath);\n\t\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\t\tassert.ok(downloadContent.equals(expectedContent));\n\t\t\t\t\tassert.equal(context.stdout, downloadStatusFixture);\n\t\t\t\t}\n\t\t\t);\n\t\tconst destination = path.join(fileDownloadPath, 'temp');\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/zip_downloads', expectedBody)\n\t\t\t\t.reply(202, createFileFixture)\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get(downloadUrl).reply(200, function () {\n\t\t\t\t\treturn fs.createReadStream(testFilePath, 'utf8');\n\t\t\t\t})\n\t\t\t)\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi.get(statusUrl).reply(200, downloadStatusFixture)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:zip',\n\t\t\t\tfileName,\n\t\t\t\t`--item=${items[0].type}:${items[0].id}`,\n\t\t\t\t`--item=${items[1].type}:${items[1].id}`,\n\t\t\t\t`--destination=${destination}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should create a zip in a non-existent path', (context) => {\n\t\t\t\tlet downloadedFilePath = path.join(destination, fileName);\n\t\t\t\tlet downloadContent = fs.readFileSync(downloadedFilePath);\n\t\t\t\tlet expectedContent = fs.readFileSync(testFilePath);\n\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\t\t\t\tfs.rmdirSync(destination, { recursive: true, force: true });\n\n\t\t\t\tassert.ok(downloadContent.equals(expectedContent));\n\t\t\t\tassert.equal(context.stdout, downloadStatusFixture);\n\t\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/zip_downloads', expectedBody)\n\t\t\t\t.reply(202, createFileFixture)\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get(downloadUrl).reply(200, function () {\n\t\t\t\t\treturn fs.createReadStream(testFilePath, 'utf8');\n\t\t\t\t})\n\t\t\t)\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi.get(statusUrl).reply(200, downloadStatusFixture)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:zip',\n\t\t\t\tfileName,\n\t\t\t\t`--item=${items[0].type}:${items[0].id}`,\n\t\t\t\t`--item=${items[1].type}:${items[1].id}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should create a zip in a default destination', (context) => {\n\t\t\t\tlet downloadedFilePath = path.join(\n\t\t\t\t\tDEFAULT_DOWNLOAD_PATH,\n\t\t\t\t\tfileName\n\t\t\t\t);\n\t\t\t\tlet downloadContent = fs.readFileSync(downloadedFilePath);\n\t\t\t\tlet expectedContent = fs.readFileSync(testFilePath);\n\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\tassert.ok(downloadContent.equals(expectedContent));\n\t\t\t\tassert.equal(context.stdout, downloadStatusFixture);\n\t\t\t});\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/zip_downloads', expectedBody)\n\t\t\t\t.reply(202, createFileFixture)\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get(downloadUrl).reply(200, function () {\n\t\t\t\t\treturn fs.createReadStream(testFilePath, 'utf8');\n\t\t\t\t})\n\t\t\t)\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi.get(statusUrl).reply(200, downloadStatusFixture)\n\t\t\t)\n\t\t\t.do(async () => {\n\t\t\t\tawait fs.writeFileSync(\n\t\t\t\t\tpath.join(DEFAULT_DOWNLOAD_PATH, fileName),\n\t\t\t\t\t'foo'\n\t\t\t\t);\n\t\t\t})\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'files:zip',\n\t\t\t\tfileName,\n\t\t\t\t`--item=${items[0].type}:${items[0].id}`,\n\t\t\t\t`--item=${items[1].type}:${items[1].id}`,\n\t\t\t\t'--overwrite',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should overwrite downloaded zip file when --overwrite flag is used',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet downloadedFilePath = path.join(\n\t\t\t\t\t\tDEFAULT_DOWNLOAD_PATH,\n\t\t\t\t\t\tfileName\n\t\t\t\t\t);\n\t\t\t\t\tlet downloadContent = fs.readFileSync(downloadedFilePath);\n\t\t\t\t\tlet expectedContent = fs.readFileSync(testFilePath);\n\t\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\t\tassert.ok(downloadContent.equals(expectedContent));\n\t\t\t\t\tassert.equal(context.stdout, downloadStatusFixture);\n\t\t\t\t}\n\t\t\t);\n\t\ttest.do(async () => {\n\t\t\tawait fs.writeFileSync(\n\t\t\t\tpath.join(DEFAULT_DOWNLOAD_PATH, fileName),\n\t\t\t\t'foo'\n\t\t\t);\n\t\t})\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'files:zip',\n\t\t\t\tfileName,\n\t\t\t\t`--item=${items[0].type}:${items[0].id}`,\n\t\t\t\t`--item=${items[1].type}:${items[1].id}`,\n\t\t\t\t'--no-overwrite',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should skip downloading zip file when exists and --no-overwrite flag is used',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet downloadedFilePath = path.join(\n\t\t\t\t\t\tDEFAULT_DOWNLOAD_PATH,\n\t\t\t\t\t\tfileName\n\t\t\t\t\t);\n\t\t\t\t\tfs.unlinkSync(downloadedFilePath);\n\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Downloading the file will not occur because the file ${downloadedFilePath} already exists, and the --no-overwrite flag is set.${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/folders.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst fs = require('fs-extra');\nconst path = require('node:path');\nconst {\n\tgetFixture,\n\tTEST_API_ROOT,\n\tTEST_UPLOAD_ROOT,\n\tTEST_DOWNLOAD_ROOT,\n\tDEFAULT_DOWNLOAD_PATH,\n\tgetDriveLetter,\n\tisWin,\n} = require('../helpers/test-helper');\nconst os = require('node:os');\nconst leche = require('leche');\nconst _ = require('lodash');\n\ndescribe('Folders', function () {\n\tdescribe('folders:get', function () {\n\t\tlet folderId = '0',\n\t\t\tgetFolderFixture = getFixture('folders/get_folders_id'),\n\t\t\tyamlOutput = getFixture('output/folders_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/folders/${folderId}`).reply(200, getFolderFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['folders:get', folderId, '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a folder (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, getFolderFixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/folders/${folderId}`).reply(200, getFolderFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['folders:get', folderId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a folder (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('folders:copy', function () {\n\t\tlet folderId = '0',\n\t\t\tparentFolderId = '987654321',\n\t\t\tname = 'Rename on copy.txt',\n\t\t\tcopyFixture = getFixture('folders/post_folders_id_copy'),\n\t\t\tyamlOutput = getFixture('output/folders_copy_yaml.txt');\n\n\t\tlet copyBody = {\n\t\t\tparent: {\n\t\t\t\tid: parentFolderId,\n\t\t\t},\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/folders/${folderId}/copy`, copyBody)\n\t\t\t\t.reply(201, copyFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:copy',\n\t\t\t\tfolderId,\n\t\t\t\tparentFolderId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should copy a folder to a different folder (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, copyFixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/folders/${folderId}/copy`, copyBody)\n\t\t\t\t.reply(201, copyFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['folders:copy', folderId, parentFolderId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should copy a folder to a different folder (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/folders/${folderId}/copy`, copyBody)\n\t\t\t\t.reply(201, copyFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:copy',\n\t\t\t\tfolderId,\n\t\t\t\tparentFolderId,\n\t\t\t\t'--id-only',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should copy a folder to a different folder (ID Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.parse(copyFixture).id}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/folders/${folderId}/copy`, {\n\t\t\t\t\t...copyBody,\n\t\t\t\t\tname,\n\t\t\t\t})\n\t\t\t\t.reply(201, copyFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:copy',\n\t\t\t\tfolderId,\n\t\t\t\tparentFolderId,\n\t\t\t\t`--name=${name}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should set optional name param when --name flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, copyFixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('folders:move', function () {\n\t\tlet folderId = '0',\n\t\t\tparentFolderId = '987654321',\n\t\t\townedById = '1234567890',\n\t\t\tmoveFixture = getFixture('folders/put_folders_id'),\n\t\t\tyamlOutput = getFixture('output/folders_move_yaml.txt');\n\n\t\tlet moveBody = {\n\t\t\t\tparent: {\n\t\t\t\t\tid: parentFolderId,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmoveBodyWithOwnedBy = {\n\t\t\t\tparent: {\n\t\t\t\t\tid: parentFolderId,\n\t\t\t\t},\n\t\t\t\towned_by: {\n\t\t\t\t\tid: ownedById,\n\t\t\t\t},\n\t\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/folders/${folderId}`, moveBody)\n\t\t\t\t.reply(200, moveFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:move',\n\t\t\t\tfolderId,\n\t\t\t\tparentFolderId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should move a folder to a different folder (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, moveFixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/folders/${folderId}`, moveBody)\n\t\t\t\t.reply(200, moveFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['folders:move', folderId, parentFolderId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should move a folder to a different folder (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/folders/${folderId}`, moveBody)\n\t\t\t\t.matchHeader('If-Match', '5')\n\t\t\t\t.reply(412, {\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\tstatus: 412,\n\t\t\t\t\tcode: 'precondition_failed',\n\t\t\t\t\thelp_url: 'http://developers.box.com/docs/#errors',\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t'The resource has been modified. Please retrieve the resource again and retry',\n\t\t\t\t\trequest_id: '1wne91fxf8871ide',\n\t\t\t\t})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:move',\n\t\t\t\tfolderId,\n\t\t\t\tparentFolderId,\n\t\t\t\t'--no-color',\n\t\t\t\t'--etag=5',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send If-Match header and throw error when etag flag is passed but does not match',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet message =\n\t\t\t\t\t\t'Unexpected API Response [412 Precondition Failed | 1wne91fxf8871ide] precondition_failed - The resource has been modified. Please retrieve the resource again and retry';\n\t\t\t\t\tassert.equal(context.stderr, `${message}${os.EOL}`);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/folders/${folderId}`, moveBodyWithOwnedBy)\n\t\t\t\t.reply(200, moveFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:move',\n\t\t\t\tfolderId,\n\t\t\t\tparentFolderId,\n\t\t\t\t`--owned-by=${ownedById}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should move a folder to a different folder and set the owner',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, moveFixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('folders:delete', function () {\n\t\tlet folderId = '12345';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.delete(`/2.0/folders/${folderId}`).reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['folders:delete', folderId, '--token=test'])\n\t\t\t.it('should delete a folder', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Deleted folder ${folderId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(`/2.0/folders/${folderId}`)\n\t\t\t\t.query({ recursive: true })\n\t\t\t\t.reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:delete',\n\t\t\t\tfolderId,\n\t\t\t\t'--recursive',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send recursive param when --recursive flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Deleted folder ${folderId}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(`/2.0/folders/${folderId}`)\n\t\t\t\t.reply(204)\n\t\t\t\t.delete(`/2.0/folders/${folderId}/trash`)\n\t\t\t\t.reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['folders:delete', folderId, '-f', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should delete a folder permanently when -f flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Deleted folder ${folderId} permanently${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(`/2.0/folders/${folderId}`)\n\t\t\t\t.matchHeader('If-Match', '5')\n\t\t\t\t.reply(412, {\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\tstatus: 412,\n\t\t\t\t\tcode: 'precondition_failed',\n\t\t\t\t\thelp_url: 'http://developers.box.com/docs/#errors',\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t'The resource has been modified. Please retrieve the resource again and retry',\n\t\t\t\t\trequest_id: '1wne91fxf8871ide',\n\t\t\t\t})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:delete',\n\t\t\t\tfolderId,\n\t\t\t\t'--no-color',\n\t\t\t\t'--etag=5',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send If-Match header and throw error when etag flag is passed but does not match',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet message =\n\t\t\t\t\t\t'Unexpected API Response [412 Precondition Failed | 1wne91fxf8871ide] precondition_failed - The resource has been modified. Please retrieve the resource again and retry';\n\t\t\t\t\tassert.equal(context.stderr, `${message}${os.EOL}`);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(`/2.0/folders/${folderId}`)\n\t\t\t\t.reply(204)\n\t\t\t\t.delete(`/2.0/folders/${folderId}/trash`)\n\t\t\t\t.reply(404)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['folders:delete', folderId, '-f', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should force delete successfully when user does not have trash enabled',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Deleted folder ${folderId} permanently${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.stdout()\n\t\t\t.stderr()\n\t\t\t.command(['folders:delete', '0', '--no-color', '--token=test'])\n\t\t\t.it('should fail for the root folder', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Cannot delete folder '0': this is the root (All Files) folder and cannot be deleted.${os.EOL}`\n\t\t\t\t);\n\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t});\n\t});\n\n\tleche.withData(\n\t\t['folders:collaborations', 'folders:collaborations:list'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet folderId = '0',\n\t\t\t\t\tgetCollaborationFixture = getFixture(\n\t\t\t\t\t\t'folders/get_folders_id_collaborations'\n\t\t\t\t\t),\n\t\t\t\t\tjsonOutput = getFixture(\n\t\t\t\t\t\t'output/folders_collaborations_list_json.txt'\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/folders/${folderId}/collaborations`)\n\t\t\t\t\t\t.reply(200, getCollaborationFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, folderId, '--json', '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should list all collaborations on a Box item (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tdescribe('folders:collaborations:add', function () {\n\t\tlet folderId = '0',\n\t\t\taddCollaborationFixture = getFixture(\n\t\t\t\t'folders/post_collaborations_user'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/folders_collaborations_add_yaml.txt'\n\t\t\t);\n\n\t\tlet addCollaborationBody = {\n\t\t\titem: {\n\t\t\t\ttype: 'folder',\n\t\t\t\tid: folderId,\n\t\t\t},\n\t\t\taccessible_by: {\n\t\t\t\ttype: 'user',\n\t\t\t\tlogin: 'newfriend@example.com',\n\t\t\t},\n\t\t\trole: 'previewer',\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody)\n\t\t\t\t.reply(200, addCollaborationFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:collaborations:add',\n\t\t\t\tfolderId,\n\t\t\t\t'--previewer',\n\t\t\t\t'--login=newfriend@example.com',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a collaboration for a Box item with the previewer and login flags passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, addCollaborationFixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody)\n\t\t\t\t.reply(200, addCollaborationFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:collaborations:add',\n\t\t\t\tfolderId,\n\t\t\t\t'--previewer',\n\t\t\t\t'--login=newfriend@example.com',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a collaboration for a Box item with the previewer and login flags passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody)\n\t\t\t\t.reply(200, addCollaborationFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:collaborations:add',\n\t\t\t\tfolderId,\n\t\t\t\t'--previewer',\n\t\t\t\t'--login=newfriend@example.com',\n\t\t\t\t'--id-only',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should output only the ID of the created collaboration when the --id-only flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.parse(addCollaborationFixture).id}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/collaborations', addCollaborationBody)\n\t\t\t\t.reply(200, addCollaborationFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:collaborations:add',\n\t\t\t\t'--previewer',\n\t\t\t\t'--login=newfriend@example.com',\n\t\t\t\tfolderId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should work with args in non-standard order', (context) => {\n\t\t\t\tassert.equal(context.stdout, addCollaborationFixture);\n\t\t\t});\n\t});\n\n\tdescribe('folders:rename', function () {\n\t\tlet folderId = '0',\n\t\t\tdescription = 'test description',\n\t\t\trenameFixture = getFixture('folders/put_folders_id'),\n\t\t\tyamlOutput = getFixture('output/folders_rename_yaml.txt');\n\n\t\tlet renameBody = {\n\t\t\tname: 'test',\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/folders/${folderId}`, renameBody)\n\t\t\t\t.reply(200, renameFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:rename',\n\t\t\t\tfolderId,\n\t\t\t\t'test',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should rename a folder (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, renameFixture);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/folders/${folderId}`, renameBody)\n\t\t\t\t.reply(200, renameFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['folders:rename', folderId, 'test', '--token=test'])\n\t\t\t.it('should rename a folder (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/folders/${folderId}`, {\n\t\t\t\t\t...renameBody,\n\t\t\t\t\tdescription,\n\t\t\t\t})\n\t\t\t\t.reply(200, renameFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:rename',\n\t\t\t\tfolderId,\n\t\t\t\t'test',\n\t\t\t\t`--description=${description}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send the description param when the --description flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, renameFixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/folders/${folderId}`, {\n\t\t\t\t\t...renameBody,\n\t\t\t\t\tdescription,\n\t\t\t\t})\n\t\t\t\t.matchHeader('If-Match', '5')\n\t\t\t\t.reply(412, {\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\tstatus: 412,\n\t\t\t\t\tcode: 'precondition_failed',\n\t\t\t\t\thelp_url: 'http://developers.box.com/docs/#errors',\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t'The resource has been modified. Please retrieve the resource again and retry',\n\t\t\t\t\trequest_id: '1wne91fxf8871ide',\n\t\t\t\t})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:rename',\n\t\t\t\tfolderId,\n\t\t\t\t'test',\n\t\t\t\t`--description=${description}`,\n\t\t\t\t'--no-color',\n\t\t\t\t'--etag=5',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send If-Match header and throw error when etag flag is passed but does not match',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet message =\n\t\t\t\t\t\t'Unexpected API Response [412 Precondition Failed | 1wne91fxf8871ide] precondition_failed - The resource has been modified. Please retrieve the resource again and retry';\n\t\t\t\t\tassert.equal(context.stderr, `${message}${os.EOL}`);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('folders:metadata:get', function () {\n\t\tlet folderId = '0',\n\t\t\tmetadataScope = 'enterprise',\n\t\t\tmetadataTemplate = 'testTemplate',\n\t\t\tgetMetadataFixture = getFixture(\n\t\t\t\t'folders/get_folders_id_metadata_scope_template'\n\t\t\t),\n\t\t\tyamlOutput = getFixture('output/folders_metadata_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(\n\t\t\t\t\t`/2.0/folders/${folderId}/metadata/${metadataScope}/${metadataTemplate}`\n\t\t\t\t)\n\t\t\t\t.reply(200, getMetadataFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:metadata:get',\n\t\t\t\tfolderId,\n\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information about a metadata object (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, getMetadataFixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(\n\t\t\t\t\t`/2.0/folders/${folderId}/metadata/${metadataScope}/${metadataTemplate}`\n\t\t\t\t)\n\t\t\t\t.reply(200, getMetadataFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:metadata:get',\n\t\t\t\tfolderId,\n\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information about a metadata object (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tleche.withData(\n\t\t['folders:metadata', 'folders:metadata:get-all'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet folderId = '0',\n\t\t\t\t\tgetAllMetadataFixture = getFixture(\n\t\t\t\t\t\t'folders/get_folders_id_metadata'\n\t\t\t\t\t),\n\t\t\t\t\tjsonOutput = getFixture(\n\t\t\t\t\t\t'output/folders_metadata_get_all_json.txt'\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/folders/${folderId}/metadata`)\n\t\t\t\t\t\t.reply(200, getAllMetadataFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, folderId, '--json', '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should get all metadata on a Box item (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tleche.withData(\n\t\t['folders:metadata:remove', 'folders:metadata:delete'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet folderId = '0',\n\t\t\t\t\tmetadataScope = 'enterprise',\n\t\t\t\t\tmetadataTemplate = 'testTemplate';\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.delete(\n\t\t\t\t\t\t\t`/2.0/folders/${folderId}/metadata/${metadataScope}/${metadataTemplate}`\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.reply(204)\n\t\t\t\t)\n\t\t\t\t\t.stderr()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tfolderId,\n\t\t\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it('should delete metadata from an item', (context) => {\n\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t\t`Successfully deleted metadata ${metadataTemplate}${os.EOL}`\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t});\n\t\t}\n\t);\n\n\tdescribe('folders:metadata:update', function () {\n\t\tlet folderId = '0',\n\t\t\tmetadataScope = 'enterprise',\n\t\t\tmetadataTemplate = 'testTemplate',\n\t\t\tgetMetadataFixture = getFixture(\n\t\t\t\t'folders/get_folders_id_metadata_scope_template'\n\t\t\t),\n\t\t\tyamlOutput = getFixture('output/folders_metadata_update_yaml.txt');\n\n\t\tlet updateMetadataBody = [\n\t\t\t{\n\t\t\t\top: 'test',\n\t\t\t\tpath: '/numReviewsLeft',\n\t\t\t\tvalue: 1,\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'replace',\n\t\t\t\tpath: '/numReviewsLeft',\n\t\t\t\tvalue: 0,\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'copy',\n\t\t\t\tfrom: '/competitiveDocument',\n\t\t\t\tpath: '/restricted',\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'add',\n\t\t\t\tpath: '/reviewedBy/-',\n\t\t\t\tvalue: 'me',\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'replace',\n\t\t\t\tpath: '/readyForRelease',\n\t\t\t\tvalue: 'yes',\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'move',\n\t\t\t\tfrom: '/reviewedBy',\n\t\t\t\tpath: '/approvedBy',\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'add',\n\t\t\t\tpath: '/dateApproved',\n\t\t\t\tvalue: '2018-12-02T11:28:55-08:00',\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'replace',\n\t\t\t\tpath: '/stepsRequiredForRelease',\n\t\t\t\tvalue: [],\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'remove',\n\t\t\t\tpath: '/embargoed',\n\t\t\t},\n\t\t];\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(\n\t\t\t\t\t`/2.0/folders/${folderId}/metadata/${metadataScope}/${metadataTemplate}`,\n\t\t\t\t\tupdateMetadataBody\n\t\t\t\t)\n\t\t\t\t.reply(200, getMetadataFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:metadata:update',\n\t\t\t\tfolderId,\n\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t'--test=/numReviewsLeft=#1',\n\t\t\t\t'--replace=/numReviewsLeft=#0',\n\t\t\t\t'--copy=/competitiveDocument>/restricted',\n\t\t\t\t'--add=reviewedBy[]=me',\n\t\t\t\t'--replace=/readyForRelease=yes',\n\t\t\t\t'--move=reviewedBy>approvedBy',\n\t\t\t\t'--add=/dateApproved=2018-12-02T11:28:55-08:00',\n\t\t\t\t'--replace=/stepsRequiredForRelease=[]',\n\t\t\t\t'--remove=/embargoed',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update metadata object with all op flags passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, getMetadataFixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(\n\t\t\t\t\t`/2.0/folders/${folderId}/metadata/${metadataScope}/${metadataTemplate}`,\n\t\t\t\t\tupdateMetadataBody\n\t\t\t\t)\n\t\t\t\t.reply(200, getMetadataFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:metadata:update',\n\t\t\t\tfolderId,\n\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t'--test=/numReviewsLeft=#1',\n\t\t\t\t'--replace=/numReviewsLeft=#0',\n\t\t\t\t'--copy=/competitiveDocument>/restricted',\n\t\t\t\t'--add=reviewedBy[]=me',\n\t\t\t\t'--replace=/readyForRelease=yes',\n\t\t\t\t'--move=reviewedBy>approvedBy',\n\t\t\t\t'--add=/dateApproved=2018-12-02T11:28:55-08:00',\n\t\t\t\t'--replace=/stepsRequiredForRelease=[]',\n\t\t\t\t'--remove=/embargoed',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update metadata object with all flags passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tleche.withData(\n\t\t['folders:metadata:add', 'folders:metadata:create'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet folderId = '0',\n\t\t\t\t\tmetadataScope = 'enterprise',\n\t\t\t\t\tmetadataTemplate = 'testTemplate',\n\t\t\t\t\taddMetadataFixture = getFixture(\n\t\t\t\t\t\t'folders/post_folders_id_metadata_scope_template'\n\t\t\t\t\t),\n\t\t\t\t\tyamlOutput = getFixture(\n\t\t\t\t\t\t'output/folders_metadata_create_yaml.txt'\n\t\t\t\t\t);\n\n\t\t\t\tlet createMetadataBody = {\n\t\t\t\t\ttest: 'test123',\n\t\t\t\t\tnumber: 1.9,\n\t\t\t\t\tarr: ['foo', 'bar'],\n\t\t\t\t};\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post(\n\t\t\t\t\t\t\t`/2.0/folders/${folderId}/metadata/${metadataScope}/${metadataTemplate}`,\n\t\t\t\t\t\t\tcreateMetadataBody\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.reply(201, addMetadataFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tfolderId,\n\t\t\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t\t\t'--data=test=test123',\n\t\t\t\t\t\t'--data=number=#1.9',\n\t\t\t\t\t\t'--data=arr=[foo,bar]',\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should add metadata object with key/value pairs passed as a flag (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, addMetadataFixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post(\n\t\t\t\t\t\t\t`/2.0/folders/${folderId}/metadata/${metadataScope}/${metadataTemplate}`,\n\t\t\t\t\t\t\tcreateMetadataBody\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.reply(201, addMetadataFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tfolderId,\n\t\t\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t\t\t'--data=test=test123',\n\t\t\t\t\t\t'--data=number=#1.9',\n\t\t\t\t\t\t'--data=arr=[foo,bar]',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should add metadata object with key/value pairs passed as a flag (YAML Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tdescribe('folders:metadata:set', function () {\n\t\tlet folderId = '0',\n\t\t\tmetadataScope = 'enterprise',\n\t\t\tmetadataTemplate = 'testTemplate',\n\t\t\taddMetadataFixture = getFixture(\n\t\t\t\t'folders/post_folders_id_metadata_scope_template'\n\t\t\t),\n\t\t\tyamlOutput = getFixture('output/folders_metadata_create_yaml.txt');\n\n\t\tlet createMetadataBody = {\n\t\t\ttest: 'test123',\n\t\t\tnumber: 1.9,\n\t\t\tarr: ['foo', 'bar'],\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(\n\t\t\t\t\t`/2.0/folders/${folderId}/metadata/${metadataScope}/${metadataTemplate}`,\n\t\t\t\t\tcreateMetadataBody\n\t\t\t\t)\n\t\t\t\t.reply(201, addMetadataFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:metadata:set',\n\t\t\t\tfolderId,\n\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t'--data=test=test123',\n\t\t\t\t'--data=number=#1.9',\n\t\t\t\t'--data=arr=[foo,bar]',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should add metadata object with key/value pairs passed as a flag (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, addMetadataFixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(\n\t\t\t\t\t`/2.0/folders/${folderId}/metadata/${metadataScope}/${metadataTemplate}`,\n\t\t\t\t\tcreateMetadataBody\n\t\t\t\t)\n\t\t\t\t.reply(201, addMetadataFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:metadata:set',\n\t\t\t\tfolderId,\n\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t'--data=test=test123',\n\t\t\t\t'--data=number=#1.9',\n\t\t\t\t'--data=arr=[foo,bar]',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should add metadata object with key/value pairs passed as a flag (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(\n\t\t\t\t\t`/2.0/folders/${folderId}/metadata/${metadataScope}/${metadataTemplate}`,\n\t\t\t\t\tcreateMetadataBody\n\t\t\t\t)\n\t\t\t\t.reply(409)\n\t\t\t\t.put(\n\t\t\t\t\t`/2.0/folders/${folderId}/metadata/${metadataScope}/${metadataTemplate}`,\n\t\t\t\t\t[\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\top: 'add',\n\t\t\t\t\t\t\tpath: '/test',\n\t\t\t\t\t\t\tvalue: 'test123',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\top: 'add',\n\t\t\t\t\t\t\tpath: '/number',\n\t\t\t\t\t\t\tvalue: 1.9,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\top: 'add',\n\t\t\t\t\t\t\tpath: '/arr',\n\t\t\t\t\t\t\tvalue: ['foo', 'bar'],\n\t\t\t\t\t\t},\n\t\t\t\t\t]\n\t\t\t\t)\n\t\t\t\t.reply(200, addMetadataFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:metadata:set',\n\t\t\t\tfolderId,\n\t\t\t\t`--template-key=${metadataTemplate}`,\n\t\t\t\t'--data=test=test123',\n\t\t\t\t'--data=number=#1.9',\n\t\t\t\t'--data=arr=[foo,bar]',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update metadata object with key/value pairs passed as a flag when creation conflicts',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, addMetadataFixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tleche.withData(\n\t\t[\n\t\t\t'folders:share',\n\t\t\t'folders:shared-links:create',\n\t\t\t'folders:shared-links:update',\n\t\t],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet folderId = '0',\n\t\t\t\t\tvanityName = 'my-custom-name-123',\n\t\t\t\t\tcreateSharedLinkFixture = getFixture(\n\t\t\t\t\t\t'folders/put_folders_id_shared_link'\n\t\t\t\t\t),\n\t\t\t\t\tunshareDate = '2030-03-04T12:34:56+00:00',\n\t\t\t\t\tjsonOutput = getFixture('output/folders_share_json.txt'),\n\t\t\t\t\tyamlOutput = getFixture('output/folders_share_yaml.txt');\n\n\t\t\t\tlet sharedLinkBody = {\n\t\t\t\t\tshared_link: {\n\t\t\t\t\t\tpermissions: { can_download: true },\n\t\t\t\t\t\taccess: 'test',\n\t\t\t\t\t\tpassword: 'test',\n\t\t\t\t\t\tvanity_name: vanityName,\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(\n\t\t\t\t\t\t\t`/2.0/folders/${folderId}?fields=shared_link`,\n\t\t\t\t\t\t\tsharedLinkBody\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.reply(200, createSharedLinkFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tfolderId,\n\t\t\t\t\t\t'--access=test',\n\t\t\t\t\t\t'--password=test',\n\t\t\t\t\t\t'--can-download',\n\t\t\t\t\t\t`--vanity-name=${vanityName}`,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should create a shared link for a Box item with access, password and can-download flags passed (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(\n\t\t\t\t\t\t\t`/2.0/folders/${folderId}?fields=shared_link`,\n\t\t\t\t\t\t\tsharedLinkBody\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.reply(200, createSharedLinkFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tfolderId,\n\t\t\t\t\t\t'--access=test',\n\t\t\t\t\t\t'--password=test',\n\t\t\t\t\t\t'--can-download',\n\t\t\t\t\t\t`--vanity-name=${vanityName}`,\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should create a shared link for a Box item with access, password and can-download flags passed (YAML Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(`/2.0/folders/${folderId}?fields=shared_link`, {\n\t\t\t\t\t\t\tshared_link: {\n\t\t\t\t\t\t\t\tpermissions: {},\n\t\t\t\t\t\t\t\tunshared_at: unshareDate,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, createSharedLinkFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tfolderId,\n\t\t\t\t\t\t`--unshared-at=${unshareDate}`,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should send unshared_at param when --unshared-at flag is passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tleche.withData(\n\t\t['folders:unshare', 'folders:shared-links:delete'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet folderId = '0',\n\t\t\t\t\tgetFolderFixture = getFixture('folders/get_folders_id');\n\n\t\t\t\tlet deleteSharedLinkBody = {\n\t\t\t\t\tshared_link: null,\n\t\t\t\t};\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(`/2.0/folders/${folderId}`, deleteSharedLinkBody)\n\t\t\t\t\t\t.reply(200, getFolderFixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.stderr()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tfolderId,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--no-color',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should delete a shared link for a folder',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t\t\t`Removed shared link from folder \"All Files\"${os.EOL}`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tleche.withData(['folders:items', 'folders:list-items'], function (command) {\n\t\tdescribe(command, function () {\n\t\t\tlet folderId = '0',\n\t\t\t\tsort = 'date',\n\t\t\t\tdirection = 'DESC',\n\t\t\t\tfixture = getFixture('folders/get_folders_id_items_page_1'),\n\t\t\t\tfixture2 = getFixture('folders/get_folders_id_items_page_2'),\n\t\t\t\tjsonOutput = getFixture('output/folders_list_items_json.txt');\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get(`/2.0/folders/${folderId}/items`)\n\t\t\t\t\t.query({ usemarker: true, limit: 1000 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get(`/2.0/folders/${folderId}/items`)\n\t\t\t\t\t.query({\n\t\t\t\t\t\tusemarker: true,\n\t\t\t\t\t\tmarker: 'page_1_marker',\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([command, folderId, '--json', '--token=test'])\n\t\t\t\t.it(\n\t\t\t\t\t'should list items in a folder (JSON Output)',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get(`/2.0/folders/${folderId}/items`)\n\t\t\t\t\t.query({\n\t\t\t\t\t\tsort,\n\t\t\t\t\t\tdirection,\n\t\t\t\t\t\tusemarker: true,\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get(`/2.0/folders/${folderId}/items`)\n\t\t\t\t\t.query({\n\t\t\t\t\t\tsort,\n\t\t\t\t\t\tdirection,\n\t\t\t\t\t\tusemarker: true,\n\t\t\t\t\t\tmarker: 'page_1_marker',\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\tfolderId,\n\t\t\t\t\t`--sort=${sort}`,\n\t\t\t\t\t`--direction=${direction}`,\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should send sorting params when --sort and --direction flags are passed',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get(`/2.0/folders/${folderId}/items`)\n\t\t\t\t\t.query({\n\t\t\t\t\t\tfields: 'created_at',\n\t\t\t\t\t\tusemarker: true,\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get(`/2.0/folders/${folderId}/items`)\n\t\t\t\t\t.query({\n\t\t\t\t\t\tfields: 'created_at',\n\t\t\t\t\t\tusemarker: true,\n\t\t\t\t\t\tmarker: 'page_1_marker',\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\tfolderId,\n\t\t\t\t\t'--fields=created_at',\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t\t);\n\t\t});\n\t});\n\n\tdescribe('folders:create', function () {\n\t\tlet parentFolderId = '0',\n\t\t\tname = 'New Folder',\n\t\t\tfixture = getFixture('folders/post_folders'),\n\t\t\tyamlOutput = getFixture('output/folders_create_yaml.txt');\n\n\t\tlet expectedBody = {\n\t\t\tparent: {\n\t\t\t\tid: parentFolderId,\n\t\t\t},\n\t\t\tname,\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/folders', expectedBody).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:create',\n\t\t\t\tparentFolderId,\n\t\t\t\tname,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should create a new folder (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/folders', expectedBody).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['folders:create', parentFolderId, name, '--token=test'])\n\t\t\t.it('should create a new folder (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/folders', expectedBody).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:create',\n\t\t\t\tparentFolderId,\n\t\t\t\tname,\n\t\t\t\t'--id-only',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a new folder with the id-only flagged passed (ID Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.parse(fixture).id}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/folders', {\n\t\t\t\t\t...expectedBody,\n\t\t\t\t})\n\t\t\t\t.reply(409, {\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\tstatus: 409,\n\t\t\t\t\tcode: 'item_name_in_use',\n\t\t\t\t\tcontext_info: {\n\t\t\t\t\t\tconflicts: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'folder',\n\t\t\t\t\t\t\t\tid: '12345',\n\t\t\t\t\t\t\t\tname: 'New Folder',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\thelp_url: 'http://developers.box.com/docs/#errors',\n\t\t\t\t\tmessage: 'Item with the same name already exists',\n\t\t\t\t\trequest_id: '1wne91fxf8871ide',\n\t\t\t\t})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:create',\n\t\t\t\tparentFolderId,\n\t\t\t\tname,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should catch and report errors with detailed context info',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedErrorOutput = `Unexpected API Response [409 Conflict | 1wne91fxf8871ide] item_name_in_use - Item with the same name already exists${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `Conflicts:${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `    -${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `        Type: folder${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `        ID: '12345'${os.EOL}`;\n\t\t\t\t\texpectedErrorOutput += `        Name: New Folder${os.EOL}`;\n\n\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t\tassert.equal(context.stderr, expectedErrorOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('folders:update', function () {\n\t\tlet folderId = '0',\n\t\t\tname = 'New Folder',\n\t\t\tdescription = 'New \\ndescription',\n\t\t\ttags = 'foo,bar',\n\t\t\tfixture = getFixture('folders/put_folders_id'),\n\t\t\tyamlOutput = getFixture('output/folders_update_yaml.txt');\n\n\t\tlet expectedBody = {\n\t\t\tname,\n\t\t\tsync_state: 'synced',\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/folders/${folderId}`, expectedBody)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:update',\n\t\t\t\tfolderId,\n\t\t\t\t`--name=${name}`,\n\t\t\t\t'--sync',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a folder with name and synced flags passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/folders/${folderId}`, expectedBody)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:update',\n\t\t\t\tfolderId,\n\t\t\t\t`--name=${name}`,\n\t\t\t\t'--sync',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a folder with name and synced flags passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/folders/${folderId}`, {\n\t\t\t\t\t...expectedBody,\n\t\t\t\t\tdescription,\n\t\t\t\t\ttags: tags.split(','),\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:update',\n\t\t\t\tfolderId,\n\t\t\t\t`--name=${name}`,\n\t\t\t\t`--description=${description}`,\n\t\t\t\t`--tags=${tags}`,\n\t\t\t\t'--sync',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send optional params when flags are passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/folders/${folderId}`, expectedBody)\n\t\t\t\t.matchHeader('If-Match', '5')\n\t\t\t\t.reply(412, {\n\t\t\t\t\ttype: 'error',\n\t\t\t\t\tstatus: 412,\n\t\t\t\t\tcode: 'precondition_failed',\n\t\t\t\t\thelp_url: 'http://developers.box.com/docs/#errors',\n\t\t\t\t\tmessage:\n\t\t\t\t\t\t'The resource has been modified. Please retrieve the resource again and retry',\n\t\t\t\t\trequest_id: '1wne91fxf8871ide',\n\t\t\t\t})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:update',\n\t\t\t\tfolderId,\n\t\t\t\t`--name=${name}`,\n\t\t\t\t'--sync',\n\t\t\t\t'--no-color',\n\t\t\t\t'--etag=5',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send If-Match header and throw error when etag flag is passed but does not match',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet message =\n\t\t\t\t\t\t'Unexpected API Response [412 Precondition Failed | 1wne91fxf8871ide] precondition_failed - The resource has been modified. Please retrieve the resource again and retry';\n\t\t\t\t\tassert.equal(context.stderr, `${message}${os.EOL}`);\n\t\t\t\t}\n\t\t\t);\n\n\t\tleche.withData(\n\t\t\t{\n\t\t\t\t'restrict collaboration flag': [\n\t\t\t\t\t'--restrict-collaboration',\n\t\t\t\t\t{ can_non_owners_invite: false },\n\t\t\t\t],\n\t\t\t\t'no restrict collaboration flag': [\n\t\t\t\t\t'--no-restrict-collaboration',\n\t\t\t\t\t{ can_non_owners_invite: true },\n\t\t\t\t],\n\t\t\t\t'restrict to enterprise flag': [\n\t\t\t\t\t'--restrict-to-enterprise',\n\t\t\t\t\t{ is_collaboration_restricted_to_enterprise: true },\n\t\t\t\t],\n\t\t\t\t'no restrict to enterprise flag': [\n\t\t\t\t\t'--no-restrict-to-enterprise',\n\t\t\t\t\t{ is_collaboration_restricted_to_enterprise: false },\n\t\t\t\t],\n\t\t\t\t'can non owners invite flag': [\n\t\t\t\t\t'--can-non-owners-invite',\n\t\t\t\t\t{ can_non_owners_invite: true },\n\t\t\t\t],\n\t\t\t\t'no can non owners invite flag': [\n\t\t\t\t\t'--no-can-non-owners-invite',\n\t\t\t\t\t{ can_non_owners_invite: false },\n\t\t\t\t],\n\t\t\t\t'can non owners view collaborations flag': [\n\t\t\t\t\t'--can-non-owners-view-collaborators',\n\t\t\t\t\t{ can_non_owners_view_collaborators: true },\n\t\t\t\t],\n\t\t\t\t'no can non owners view collaborations flag': [\n\t\t\t\t\t'--no-can-non-owners-view-collaborators',\n\t\t\t\t\t{ can_non_owners_view_collaborators: false },\n\t\t\t\t],\n\t\t\t\t'upload email access flag': [\n\t\t\t\t\t'--upload-email-access=open',\n\t\t\t\t\t{ folder_upload_email: { access: 'open' } },\n\t\t\t\t],\n\t\t\t\t'sync flag': ['--sync', { sync_state: 'synced' }],\n\t\t\t\t'no sync flag': ['--no-sync', { sync_state: 'not_synced' }],\n\t\t\t},\n\t\t\tfunction (flag, expectedData) {\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(`/2.0/folders/${folderId}`, expectedData)\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.stderr()\n\t\t\t\t\t.command(['folders:update', folderId, flag, '--token=test'])\n\t\t\t\t\t.it('should send correct updates when flag is passed');\n\t\t\t}\n\t\t);\n\t});\n\n\tdescribe('folders:upload', function () {\n\t\tlet parentFolderId = '1234',\n\t\t\tname1 = 'test_folder',\n\t\t\tname2 = 'nested_folder',\n\t\t\tfolderId = '22222',\n\t\t\tfolderPath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'..',\n\t\t\t\t'fixtures/folders/test_folder'\n\t\t\t),\n\t\t\ttestFileName = 'test_file.txt',\n\t\t\tcreateFolderFixture = getFixture('folders/post_folders'),\n\t\t\tuploadFileFixture = getFixture('folders/post_files_content'),\n\t\t\tgetFolderFixture = getFixture('folders/get_folders_id'),\n\t\t\tyamlOutput = getFixture('output/folders_upload_yaml.txt');\n\n\t\tlet expectedBody1 = {\n\t\t\tparent: {\n\t\t\t\tid: parentFolderId,\n\t\t\t},\n\t\t\tname: name1,\n\t\t};\n\t\tlet expectedBody2 = {\n\t\t\tparent: {\n\t\t\t\tid: folderId,\n\t\t\t},\n\t\t\tname: name2,\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/folders', expectedBody1)\n\t\t\t\t.reply(201, createFolderFixture)\n\t\t\t\t.post('/2.0/folders', expectedBody2)\n\t\t\t\t.reply(201, createFolderFixture)\n\t\t)\n\t\t\t.nock(TEST_UPLOAD_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.post('/2.0/files/content', (body) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tlet lines = body.split(/\\r?\\n/u);\n\t\t\t\t\t\t\tlet attributes = JSON.parse(lines[3]);\n\t\t\t\t\t\t\tassert.propertyVal(\n\t\t\t\t\t\t\t\tattributes,\n\t\t\t\t\t\t\t\t'name',\n\t\t\t\t\t\t\t\ttestFileName\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t})\n\t\t\t\t\t.reply(201, uploadFileFixture)\n\t\t\t\t\t.post('/2.0/files/content', (body) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tlet lines = body.split(/\\r?\\n/u);\n\t\t\t\t\t\t\tlet attributes = JSON.parse(lines[3]);\n\t\t\t\t\t\t\tassert.propertyVal(\n\t\t\t\t\t\t\t\tattributes,\n\t\t\t\t\t\t\t\t'name',\n\t\t\t\t\t\t\t\ttestFileName\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t})\n\t\t\t\t\t.reply(201, uploadFileFixture)\n\t\t\t)\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi.get(`/2.0/folders/${folderId}`).reply(200, getFolderFixture)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:upload',\n\t\t\t\tfolderPath,\n\t\t\t\t`--parent-folder=${parentFolderId}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should upload a folder (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, getFolderFixture);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/folders', expectedBody1)\n\t\t\t\t.reply(201, createFolderFixture)\n\t\t\t\t.post('/2.0/folders', expectedBody2)\n\t\t\t\t.reply(201, createFolderFixture)\n\t\t)\n\t\t\t.nock(TEST_UPLOAD_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.post('/2.0/files/content', (body) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tlet lines = body.split(/\\r?\\n/u);\n\t\t\t\t\t\t\tlet attributes = JSON.parse(lines[3]);\n\t\t\t\t\t\t\tassert.propertyVal(\n\t\t\t\t\t\t\t\tattributes,\n\t\t\t\t\t\t\t\t'name',\n\t\t\t\t\t\t\t\ttestFileName\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t})\n\t\t\t\t\t.reply(201, uploadFileFixture)\n\t\t\t\t\t.post('/2.0/files/content', (body) => {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tlet lines = body.split(/\\r?\\n/u);\n\t\t\t\t\t\t\tlet attributes = JSON.parse(lines[3]);\n\t\t\t\t\t\t\tassert.propertyVal(\n\t\t\t\t\t\t\t\tattributes,\n\t\t\t\t\t\t\t\t'name',\n\t\t\t\t\t\t\t\ttestFileName\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t})\n\t\t\t\t\t.reply(201, uploadFileFixture)\n\t\t\t)\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi.get(`/2.0/folders/${folderId}`).reply(200, getFolderFixture)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:upload',\n\t\t\t\tfolderPath,\n\t\t\t\t`--parent-folder=${parentFolderId}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should upload a folder (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\t});\n\n\tdescribe('folders:download', function () {\n\t\tlet downloadPath = path.join(\n\t\t\t\t__dirname,\n\t\t\t\t'../fixtures/folders/test_folder_download'\n\t\t\t),\n\t\t\tfolderID = '11111',\n\t\t\tfolderName = 'DownloadFolderTest',\n\t\t\tgetFolderFixture = getFixture(\n\t\t\t\t'folders/get_folders_id_folder_download'\n\t\t\t),\n\t\t\tgetSubfolderFixture = getFixture(\n\t\t\t\t'folders/get_folders_id_subfolder_download'\n\t\t\t),\n\t\t\tgetLargeFolderFixture = getFixture(\n\t\t\t\t'folders/get_folders_id_large_folder'\n\t\t\t),\n\t\t\tlargeFolderPage1Fixture = getFixture(\n\t\t\t\t'folders/get_folders_id_items_page_1_folder_download'\n\t\t\t),\n\t\t\tlargeFolderPage2Fixture = getFixture(\n\t\t\t\t'folders/get_folders_id_items_page_2_folder_download'\n\t\t\t);\n\n\t\tlet expectedContents = {\n\t\t\t'file 1.txt': 'File 1 contents',\n\t\t\t'file 2.txt': 'File 2 contents',\n\t\t\tsubfolder: {\n\t\t\t\t'subfolder file 1.txt': 'File 3 contents',\n\t\t\t},\n\t\t};\n\n\t\tfunction getDirectoryContents(folderPath) {\n\t\t\tlet object = {};\n\t\t\tlet folderContents = fs.readdirSync(folderPath);\n\t\t\tfor (const item of folderContents) {\n\t\t\t\tlet itemPath = path.join(folderPath, item);\n\t\t\t\tlet stat = fs.statSync(itemPath);\n\t\t\t\tobject[item] = stat.isDirectory()\n\t\t\t\t\t? getDirectoryContents(itemPath)\n\t\t\t\t\t: fs.readFileSync(itemPath, 'utf8');\n\t\t\t}\n\n\t\t\treturn object;\n\t\t}\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/folders/${folderID}`)\n\t\t\t\t.reply(200, getFolderFixture)\n\t\t\t\t.get('/2.0/folders/22222')\n\t\t\t\t.reply(200, getSubfolderFixture)\n\t\t\t\t.get('/2.0/files/77777/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/77777` })\n\t\t\t\t.get('/2.0/files/44444/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/44444` })\n\t\t\t\t.get('/2.0/files/55555/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/55555` })\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/44444')\n\t\t\t\t\t.reply(200, expectedContents['file 1.txt'])\n\t\t\t\t\t.get('/55555')\n\t\t\t\t\t.reply(200, expectedContents['file 2.txt'])\n\t\t\t\t\t.get('/77777')\n\t\t\t\t\t.reply(\n\t\t\t\t\t\t200,\n\t\t\t\t\t\texpectedContents.subfolder['subfolder file 1.txt']\n\t\t\t\t\t)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:download',\n\t\t\t\tfolderID,\n\t\t\t\t`--destination=${downloadPath}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should download folder to specified path on disk when called with destination flag',\n\t\t\t\tasync (context) => {\n\t\t\t\t\tlet folderPath = path.join(downloadPath, folderName);\n\t\t\t\t\tlet actualContents = getDirectoryContents(folderPath);\n\t\t\t\t\tawait fs.remove(downloadPath);\n\n\t\t\t\t\tassert.deepEqual(actualContents, expectedContents);\n\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) => {\n\t\t\tapi.get(`/2.0/folders/${folderID}`)\n\t\t\t\t.reply(200, getLargeFolderFixture)\n\t\t\t\t.get(`/2.0/folders/${folderID}/items`)\n\t\t\t\t.query({\n\t\t\t\t\tusemarker: true,\n\t\t\t\t\tfields: 'type,id,name',\n\t\t\t\t})\n\t\t\t\t.reply(200, largeFolderPage1Fixture)\n\t\t\t\t.get(`/2.0/folders/${folderID}/items`)\n\t\t\t\t.query({\n\t\t\t\t\tusemarker: true,\n\t\t\t\t\tfields: 'type,id,name',\n\t\t\t\t\tmarker: 'page_1_marker',\n\t\t\t\t})\n\t\t\t\t.reply(200, largeFolderPage2Fixture);\n\n\t\t\tfor (let index = 1; index <= 200; index++) {\n\t\t\t\tapi.get(`/2.0/files/${index}/content`).reply(302, '', {\n\t\t\t\t\tLocation: `${TEST_DOWNLOAD_ROOT}/${index}`,\n\t\t\t\t});\n\t\t\t}\n\t\t})\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) => {\n\t\t\t\tfor (let index = 1; index <= 200; index++) {\n\t\t\t\t\tapi.get(`/${index}`).reply(200, `File ${index} contents`);\n\t\t\t\t}\n\t\t\t})\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:download',\n\t\t\t\tfolderID,\n\t\t\t\t`--destination=${downloadPath}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should correctly download contents when Box folder has many items',\n\t\t\t\tasync (context) => {\n\t\t\t\t\tlet manyFilesExpectedContents = {};\n\t\t\t\t\tfor (let index = 1; index <= 200; index++) {\n\t\t\t\t\t\tmanyFilesExpectedContents[`file ${index}.txt`] =\n\t\t\t\t\t\t\t`File ${index} contents`;\n\t\t\t\t\t}\n\t\t\t\t\tlet folderPath = path.join(downloadPath, folderName);\n\t\t\t\t\tlet actualContents = getDirectoryContents(folderPath);\n\t\t\t\t\tawait fs.remove(downloadPath);\n\n\t\t\t\t\tassert.deepEqual(actualContents, manyFilesExpectedContents);\n\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t}\n\t\t\t)\n\t\t\t.timeout(60_000);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/folders/${folderID}`)\n\t\t\t\t.reply(200, getFolderFixture)\n\t\t\t\t.get('/2.0/files/44444/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/44444` })\n\t\t\t\t.get('/2.0/files/55555/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/55555` })\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/44444')\n\t\t\t\t\t.reply(200, expectedContents['file 1.txt'])\n\t\t\t\t\t.get('/55555')\n\t\t\t\t\t.reply(200, expectedContents['file 2.txt'])\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:download',\n\t\t\t\tfolderID,\n\t\t\t\t`--destination=${downloadPath}`,\n\t\t\t\t'--depth=0',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should only download files in top-level folder when --depth=0 flag is passed',\n\t\t\t\tasync (context) => {\n\t\t\t\t\tlet folderPath = path.join(downloadPath, folderName);\n\t\t\t\t\tlet actualContents = getDirectoryContents(folderPath);\n\t\t\t\t\tawait fs.remove(downloadPath);\n\n\t\t\t\t\tassert.deepEqual(\n\t\t\t\t\t\tactualContents,\n\t\t\t\t\t\t_.omit(expectedContents, 'subfolder')\n\t\t\t\t\t);\n\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/folders/${folderID}`)\n\t\t\t\t.reply(200, getFolderFixture)\n\t\t\t\t.get('/2.0/folders/22222')\n\t\t\t\t.reply(200, getSubfolderFixture)\n\t\t\t\t.get('/2.0/files/77777/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/77777` })\n\t\t\t\t.get('/2.0/files/44444/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/44444` })\n\t\t\t\t.get('/2.0/files/55555/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/55555` })\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/44444')\n\t\t\t\t\t.reply(200, expectedContents['file 1.txt'])\n\t\t\t\t\t.get('/55555')\n\t\t\t\t\t.reply(200, expectedContents['file 2.txt'])\n\t\t\t\t\t.get('/77777')\n\t\t\t\t\t.reply(\n\t\t\t\t\t\t200,\n\t\t\t\t\t\texpectedContents.subfolder['subfolder file 1.txt']\n\t\t\t\t\t)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:download',\n\t\t\t\tfolderID,\n\t\t\t\t`--destination=${downloadPath}`,\n\t\t\t\t'--zip',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should download folder to zip file when --zip flag is passed',\n\t\t\t\tasync (context) => {\n\t\t\t\t\t// Find zip file in directory\n\t\t\t\t\tconst files = await fs.readdir(downloadPath);\n\t\t\t\t\tlet filename = files.find(\n\t\t\t\t\t\t(f) =>\n\t\t\t\t\t\t\tf.startsWith(`folders-download-${folderID}`) &&\n\t\t\t\t\t\t\tf.endsWith('.zip')\n\t\t\t\t\t);\n\t\t\t\t\tawait fs.remove(downloadPath);\n\n\t\t\t\t\t// @TODO(2018-10-30): Verify contents of zip file\n\n\t\t\t\t\tassert.ok(filename, 'File shoudl have been found');\n\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:download',\n\t\t\t\tfolderID,\n\t\t\t\t'--destination=/path/really/should/not/exist',\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t\t'--no-create-path',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should output error when destination directory does not exist',\n\t\t\t\t(context) => {\n\t\t\t\t\tconst filePath = isWin()\n\t\t\t\t\t\t? String.raw`${getDriveLetter()}\\path\\really\\should\\not\\exist`\n\t\t\t\t\t\t: '/path/really/should/not/exist';\n\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`The ${filePath} path does not exist. Either create it, or pass the --create-path flag set to true${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\tconst destination = `${downloadPath}/temp`;\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/folders/${folderID}`)\n\t\t\t\t.reply(200, getFolderFixture)\n\t\t\t\t.get('/2.0/folders/22222')\n\t\t\t\t.reply(200, getSubfolderFixture)\n\t\t\t\t.get('/2.0/files/77777/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/77777` })\n\t\t\t\t.get('/2.0/files/44444/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/44444` })\n\t\t\t\t.get('/2.0/files/55555/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/55555` })\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/44444')\n\t\t\t\t\t.reply(200, expectedContents['file 1.txt'])\n\t\t\t\t\t.get('/55555')\n\t\t\t\t\t.reply(200, expectedContents['file 2.txt'])\n\t\t\t\t\t.get('/77777')\n\t\t\t\t\t.reply(\n\t\t\t\t\t\t200,\n\t\t\t\t\t\texpectedContents.subfolder['subfolder file 1.txt']\n\t\t\t\t\t)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:download',\n\t\t\t\tfolderID,\n\t\t\t\t`--destination=${destination}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should download a folder a non-existent path',\n\t\t\t\tasync (context) => {\n\t\t\t\t\tlet folderPath = path.join(destination, folderName);\n\t\t\t\t\tlet actualContents = getDirectoryContents(folderPath);\n\t\t\t\t\tawait fs.remove(destination);\n\n\t\t\t\t\tassert.deepEqual(actualContents, expectedContents);\n\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/folders/${folderID}`)\n\t\t\t\t.reply(200, getFolderFixture)\n\t\t\t\t.get('/2.0/folders/22222')\n\t\t\t\t.reply(200, getSubfolderFixture)\n\t\t\t\t.get('/2.0/files/77777/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/77777` })\n\t\t\t\t.get('/2.0/files/44444/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/44444` })\n\t\t\t\t.get('/2.0/files/55555/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/55555` })\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/44444')\n\t\t\t\t\t.reply(200, expectedContents['file 1.txt'])\n\t\t\t\t\t.get('/55555')\n\t\t\t\t\t.reply(200, expectedContents['file 2.txt'])\n\t\t\t\t\t.get('/77777')\n\t\t\t\t\t.reply(\n\t\t\t\t\t\t200,\n\t\t\t\t\t\texpectedContents.subfolder['subfolder file 1.txt']\n\t\t\t\t\t)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command(['folders:download', folderID, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should download a folder to a default destination',\n\t\t\t\tasync (context) => {\n\t\t\t\t\tlet folderPath = path.join(\n\t\t\t\t\t\tDEFAULT_DOWNLOAD_PATH,\n\t\t\t\t\t\tfolderName\n\t\t\t\t\t);\n\t\t\t\t\tlet actualContents = getDirectoryContents(folderPath);\n\t\t\t\t\tawait fs.remove(folderPath);\n\n\t\t\t\t\tassert.deepEqual(actualContents, expectedContents);\n\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/folders/${folderID}`)\n\t\t\t\t.reply(200, getFolderFixture)\n\t\t\t\t.get('/2.0/folders/22222')\n\t\t\t\t.reply(200, getSubfolderFixture)\n\t\t\t\t.get('/2.0/files/77777/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/77777` })\n\t\t\t\t.get('/2.0/files/44444/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/44444` })\n\t\t\t\t.get('/2.0/files/55555/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/55555` })\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/44444')\n\t\t\t\t\t.reply(200, expectedContents['file 1.txt'])\n\t\t\t\t\t.get('/55555')\n\t\t\t\t\t.reply(200, expectedContents['file 2.txt'])\n\t\t\t\t\t.get('/77777')\n\t\t\t\t\t.reply(\n\t\t\t\t\t\t200,\n\t\t\t\t\t\texpectedContents.subfolder['subfolder file 1.txt']\n\t\t\t\t\t)\n\t\t\t)\n\t\t\t.do(() => {\n\t\t\t\tconst folderPath = path.join(destination, folderName);\n\t\t\t\tif (fs.existsSync(destination)) {\n\t\t\t\t\tfs.removeSync(destination);\n\t\t\t\t}\n\t\t\t\tfs.mkdirSync(destination);\n\t\t\t\tfs.mkdirSync(folderPath);\n\t\t\t\tfs.writeFileSync(\n\t\t\t\t\tpath.join(folderPath, 'file 1.txt'),\n\t\t\t\t\t'test123'\n\t\t\t\t);\n\t\t\t})\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:download',\n\t\t\t\tfolderID,\n\t\t\t\t`--destination=${destination}`,\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should download and overwrite existing folder',\n\t\t\t\tasync (context) => {\n\t\t\t\t\tlet folderPath = path.join(destination, folderName);\n\t\t\t\t\tlet actualContents = getDirectoryContents(folderPath);\n\t\t\t\t\tawait fs.remove(destination);\n\n\t\t\t\t\tassert.deepEqual(actualContents, expectedContents);\n\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/folders/${folderID}`)\n\t\t\t\t.reply(200, getFolderFixture)\n\t\t\t\t.get('/2.0/folders/22222')\n\t\t\t\t.reply(200, getSubfolderFixture)\n\t\t\t\t.get('/2.0/files/77777/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/77777` })\n\t\t\t\t.get('/2.0/files/55555/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/55555` })\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/55555')\n\t\t\t\t\t.reply(200, expectedContents['file 2.txt'])\n\t\t\t\t\t.get('/77777')\n\t\t\t\t\t.reply(\n\t\t\t\t\t\t200,\n\t\t\t\t\t\texpectedContents.subfolder['subfolder file 1.txt']\n\t\t\t\t\t)\n\t\t\t)\n\t\t\t.do(() => {\n\t\t\t\tconst folderPath = path.join(destination, folderName);\n\t\t\t\tif (fs.existsSync(destination)) {\n\t\t\t\t\tfs.removeSync(destination);\n\t\t\t\t}\n\t\t\t\tfs.mkdirSync(destination);\n\t\t\t\tfs.mkdirSync(folderPath);\n\t\t\t\tfs.writeFileSync(\n\t\t\t\t\tpath.join(folderPath, 'file 1.txt'),\n\t\t\t\t\t'test123'\n\t\t\t\t);\n\t\t\t})\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:download',\n\t\t\t\tfolderID,\n\t\t\t\t`--destination=${destination}`,\n\t\t\t\t'--no-color',\n\t\t\t\t'--no-overwrite',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should not overwrite existing folder when --no-overwrite flag is passed',\n\t\t\t\tasync (context) => {\n\t\t\t\t\tlet folderPath = path.join(destination, folderName);\n\t\t\t\t\tlet actualContents = getDirectoryContents(folderPath);\n\t\t\t\t\tawait fs.remove(destination);\n\t\t\t\t\tassert.equal(actualContents['file 1.txt'], 'test123');\n\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/folders/${folderID}`)\n\t\t\t\t.reply(200, getFolderFixture)\n\t\t\t\t.get('/2.0/files/55555/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/55555` })\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi.get('/55555').reply(200, expectedContents['file 2.txt'])\n\t\t\t)\n\t\t\t.do(() => {\n\t\t\t\tconst folderPath = path.join(destination, folderName);\n\t\t\t\tif (fs.existsSync(destination)) {\n\t\t\t\t\tfs.removeSync(destination);\n\t\t\t\t}\n\t\t\t\tfs.mkdirSync(destination);\n\t\t\t\tfs.mkdirSync(folderPath);\n\t\t\t\tfs.mkdirSync(path.join(folderPath, 'subfolder'));\n\t\t\t\tfs.writeFileSync(\n\t\t\t\t\tpath.join(folderPath, 'file 1.txt'),\n\t\t\t\t\t'test123'\n\t\t\t\t);\n\t\t\t})\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:download',\n\t\t\t\tfolderID,\n\t\t\t\t`--destination=${destination}`,\n\t\t\t\t'--no-color',\n\t\t\t\t'--no-overwrite',\n\t\t\t\t'--depth=0',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should not overwrite existing file and folder in root folder when --no-overwrite and --depth=0 flag is passed',\n\t\t\t\tasync (context) => {\n\t\t\t\t\tlet folderPath = path.join(destination, folderName);\n\t\t\t\t\tlet actualContents = getDirectoryContents(folderPath);\n\t\t\t\t\tawait fs.remove(destination);\n\t\t\t\t\tassert.equal(actualContents['file 1.txt'], 'test123');\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tObject.keys(actualContents.subfolder).length,\n\t\t\t\t\t\t0\n\t\t\t\t\t);\n\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/folders/${folderID}`)\n\t\t\t\t.reply(200, getFolderFixture)\n\t\t\t\t.get('/2.0/folders/22222')\n\t\t\t\t.reply(200, getSubfolderFixture)\n\t\t\t\t.get('/2.0/files/77777/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/77777` })\n\t\t\t\t.get('/2.0/files/55555/content')\n\t\t\t\t.reply(302, '', { Location: `${TEST_DOWNLOAD_ROOT}/55555` })\n\t\t)\n\t\t\t.nock(TEST_DOWNLOAD_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/55555')\n\t\t\t\t\t.reply(200, expectedContents['file 2.txt'])\n\t\t\t\t\t.get('/77777')\n\t\t\t\t\t.reply(\n\t\t\t\t\t\t200,\n\t\t\t\t\t\texpectedContents.subfolder['subfolder file 1.txt']\n\t\t\t\t\t)\n\t\t\t)\n\t\t\t.do(() => {\n\t\t\t\tconst folderPath = path.join(destination, folderName);\n\t\t\t\tif (fs.existsSync(destination)) {\n\t\t\t\t\tfs.removeSync(destination);\n\t\t\t\t}\n\t\t\t\tfs.mkdirSync(destination);\n\t\t\t\tfs.mkdirSync(folderPath);\n\t\t\t\tfs.mkdirSync(path.join(folderPath, 'subfolder'));\n\t\t\t\tfs.writeFileSync(\n\t\t\t\t\tpath.join(folderPath, 'file 1.txt'),\n\t\t\t\t\t'test123'\n\t\t\t\t);\n\t\t\t})\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'folders:download',\n\t\t\t\tfolderID,\n\t\t\t\t`--destination=${destination}`,\n\t\t\t\t'--no-color',\n\t\t\t\t'--no-overwrite',\n\t\t\t\t'--depth=10',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should not overwrite existing file and folder in folder recursively when --no-overwrite and --depth=10 flag is passed',\n\t\t\t\tasync (context) => {\n\t\t\t\t\tlet folderPath = path.join(destination, folderName);\n\t\t\t\t\tlet actualContents = getDirectoryContents(folderPath);\n\t\t\t\t\tawait fs.remove(destination);\n\t\t\t\t\tassert.equal(actualContents['file 1.txt'], 'test123');\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tObject.keys(actualContents.subfolder).length,\n\t\t\t\t\t\t1\n\t\t\t\t\t);\n\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('folders:locks', function () {\n\t\tlet folderId = '0',\n\t\t\tfixture = getFixture('folders/get_folder_locks'),\n\t\t\tjsonOutput = getFixture('output/folders_locks_list_json.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/folder_locks')\n\t\t\t\t.query({ folder_id: folderId })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['folders:locks', folderId, '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should list all locks on a folder (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('folders:locks:create', function () {\n\t\tlet folderId = '22222',\n\t\t\tfixture = getFixture('folders/post_folder_locks');\n\n\t\tlet expectedBody = {\n\t\t\tfolder: {\n\t\t\t\ttype: 'folder',\n\t\t\t\tid: folderId,\n\t\t\t},\n\t\t\tlocked_operations: {\n\t\t\t\tmove: true,\n\t\t\t\tdelete: true,\n\t\t\t},\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/folder_locks', expectedBody).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'folders:locks:create',\n\t\t\t\tfolderId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should create a lock on a folder (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\t});\n\n\tdescribe('folders:locks:delete', function () {\n\t\tlet folderLockId = '0';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.delete(`/2.0/folder_locks/${folderLockId}`).reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['folders:locks:delete', folderLockId, '--token=test'])\n\t\t\t.it('should delete a lock on folder', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Delete folder lock with ID ${folderLockId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/commands/groups.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\nconst leche = require('leche');\n\ndescribe('Groups', function () {\n\tdescribe('groups:get', function () {\n\t\tlet groupId = '11111',\n\t\t\tfixture = getFixture('groups/get_groups_id'),\n\t\t\tyamlOutput = getFixture('output/groups_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/groups/${groupId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['groups:get', groupId, '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a group (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/groups/${groupId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['groups:get', groupId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a group (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/groups/${groupId}`)\n\t\t\t\t.query({ fields: 'id,name' })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'groups:get',\n\t\t\t\tgroupId,\n\t\t\t\t'--fields=id,name',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tleche.withData(['groups', 'groups:list'], function (command) {\n\t\tdescribe(command, function () {\n\t\t\tlet fixture = getFixture('groups/get_groups_page_1'),\n\t\t\t\tfixture2 = getFixture('groups/get_groups_page_2'),\n\t\t\t\tjsonOutput = getFixture('output/groups_list_json.txt');\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/groups')\n\t\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get('/2.0/groups')\n\t\t\t\t\t.query({\n\t\t\t\t\t\toffset: 2,\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([command, '--json', '--token=test'])\n\t\t\t\t.it('should list all groups (JSON Output)', (context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t});\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/groups')\n\t\t\t\t\t.query({ fields: 'id,name', limit: 1000 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get('/2.0/groups')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tfields: 'id,name',\n\t\t\t\t\t\toffset: 2,\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\t'--fields=id,name',\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t\t);\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/groups')\n\t\t\t\t\t.query({ filter_term: 'Employees', limit: 1000 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get('/2.0/groups')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tfilter_term: 'Employees',\n\t\t\t\t\t\toffset: 2,\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\t'--filter=Employees',\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should send filter_term param to the API when --filter flag is passed'\n\t\t\t\t);\n\t\t});\n\t});\n\n\tleche.withData(\n\t\t[\n\t\t\t'groups:list-collaborations',\n\t\t\t'groups:collaborations',\n\t\t\t'collaborations:list-for-group',\n\t\t],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet groupId = '119720',\n\t\t\t\t\tfixture = getFixture(\n\t\t\t\t\t\t'groups/get_groups_id_collaborations_page_1'\n\t\t\t\t\t),\n\t\t\t\t\tfixture2 = getFixture(\n\t\t\t\t\t\t'groups/get_groups_id_collaborations_page_2'\n\t\t\t\t\t),\n\t\t\t\t\tjsonOutput = getFixture(\n\t\t\t\t\t\t'output/groups_list_collaborations_json.txt'\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/groups/${groupId}/collaborations`)\n\t\t\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t.get(`/2.0/groups/${groupId}/collaborations`)\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\toffset: 1,\n\t\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, groupId, '--json', '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should list collaborations for a group (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/groups/${groupId}/collaborations`)\n\t\t\t\t\t\t.query({ fields: 'item', limit: 1000 })\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t.get(`/2.0/groups/${groupId}/collaborations`)\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\tfields: 'item',\n\t\t\t\t\t\t\toffset: 1,\n\t\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tgroupId,\n\t\t\t\t\t\t'--fields=item',\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tdescribe('groups:delete', function () {\n\t\tlet groupId = '11111';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.delete(`/2.0/groups/${groupId}`).reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['groups:delete', groupId, '--token=test'])\n\t\t\t.it('should delete a group', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Deleted group ${groupId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tdescribe('groups:update', function () {\n\t\tlet groupId = '11111',\n\t\t\tname = 'Remote Employees',\n\t\t\tmembers = 'all_managed_users',\n\t\t\tdescription = 'All employees not at HQ',\n\t\t\tprovenance = 'Somewhere',\n\t\t\texternalSyncIdentifier = 'some',\n\t\t\tfixture = getFixture('groups/put_groups_id'),\n\t\t\tyamlOutput = getFixture('output/groups_update_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.put(`/2.0/groups/${groupId}`, { name }).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'groups:update',\n\t\t\t\tgroupId,\n\t\t\t\t`--name=${name}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a group with name, invite and view-member flags passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.put(`/2.0/groups/${groupId}`, { name }).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'groups:update',\n\t\t\t\tgroupId,\n\t\t\t\t`--name=${name}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a group with name, invite and view-member flags passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/groups/${groupId}`, {\n\t\t\t\t\tdescription,\n\t\t\t\t\tinvitability_level: members,\n\t\t\t\t\tmember_viewability_level: members,\n\t\t\t\t\tprovenance,\n\t\t\t\t\texternal_sync_identifier: externalSyncIdentifier,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'groups:update',\n\t\t\t\tgroupId,\n\t\t\t\t`--description=${description}`,\n\t\t\t\t`--invite=${members}`,\n\t\t\t\t`--provenance=${provenance}`,\n\t\t\t\t`--external-sync-identifier=${externalSyncIdentifier}`,\n\t\t\t\t`--view-members=${members}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send optional params when flags are passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('groups:create', function () {\n\t\tlet name = 'Employees',\n\t\t\tmembers = 'all_managed_users',\n\t\t\tprovenance = 'Elsewhere',\n\t\t\tdescription = 'Everyone',\n\t\t\texternalSyncIdentifier = 'else',\n\t\t\tfixture = getFixture('groups/post_groups'),\n\t\t\tyamlOutput = getFixture('output/groups_create_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/groups', { name }).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['groups:create', name, '--json', '--token=test'])\n\t\t\t.it('should create a group (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/groups', { name }).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['groups:create', name, '--token=test'])\n\t\t\t.it('should create a group (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/groups', { name }).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['groups:create', name, '--id-only', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should output only the ID of the new group when --id-only flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.parse(fixture).id}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/groups', {\n\t\t\t\t\tname,\n\t\t\t\t\tdescription,\n\t\t\t\t\tinvitability_level: members,\n\t\t\t\t\tmember_viewability_level: members,\n\t\t\t\t\tprovenance,\n\t\t\t\t\texternal_sync_identifier: externalSyncIdentifier,\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'groups:create',\n\t\t\t\tname,\n\t\t\t\t`--description=${description}`,\n\t\t\t\t`--invite=${members}`,\n\t\t\t\t`--provenance=${provenance}`,\n\t\t\t\t`--external-sync-identifier=${externalSyncIdentifier}`,\n\t\t\t\t`--view-members=${members}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send optional params when flags are passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tleche.withData(\n\t\t['groups:memberships:get', 'groups:membership:get'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet membershipId = '12345',\n\t\t\t\t\tfixture = getFixture('groups/get_group_memberships_id'),\n\t\t\t\t\tyamlOutput = getFixture(\n\t\t\t\t\t\t'output/groups_membership_get_yaml.txt'\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/group_memberships/${membershipId}`)\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, membershipId, '--json', '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should get information about a group membership (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/group_memberships/${membershipId}`)\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, membershipId, '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should get information about a group membership (YAML Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/group_memberships/${membershipId}`)\n\t\t\t\t\t\t.query({ fields: 'id' })\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tmembershipId,\n\t\t\t\t\t\t'--fields=id',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tleche.withData(\n\t\t['groups:memberships', 'groups:membership:list'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet groupId = '11111',\n\t\t\t\t\tfixture = getFixture(\n\t\t\t\t\t\t'groups/get_groups_id_memberships_page_1'\n\t\t\t\t\t),\n\t\t\t\t\tfixture2 = getFixture(\n\t\t\t\t\t\t'groups/get_groups_id_memberships_page_2'\n\t\t\t\t\t),\n\t\t\t\t\tjsonOutput = getFixture(\n\t\t\t\t\t\t'output/groups_membership_list_json.txt'\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/groups/${groupId}/memberships`)\n\t\t\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t.get(`/2.0/groups/${groupId}/memberships`)\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\toffset: 1,\n\t\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, groupId, '--json', '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should list members of a group (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/groups/${groupId}/memberships`)\n\t\t\t\t\t\t.query({ fields: 'user', limit: 1000 })\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t.get(`/2.0/groups/${groupId}/memberships`)\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\tfields: 'user',\n\t\t\t\t\t\t\toffset: 1,\n\t\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tgroupId,\n\t\t\t\t\t\t'--fields=user',\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tleche.withData(\n\t\t['groups:memberships:add', 'groups:membership:add'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet groupId = '11111',\n\t\t\t\t\tuserId = '44444',\n\t\t\t\t\tfixture = getFixture('groups/post_group_memberships'),\n\t\t\t\t\tyamlOutput = getFixture(\n\t\t\t\t\t\t'output/groups_membership_add_yaml.txt'\n\t\t\t\t\t);\n\n\t\t\t\tlet expectedBody = {\n\t\t\t\t\trole: 'member',\n\t\t\t\t\tgroup: {\n\t\t\t\t\t\tid: groupId,\n\t\t\t\t\t},\n\t\t\t\t\tuser: {\n\t\t\t\t\t\tid: userId,\n\t\t\t\t\t},\n\t\t\t\t\tconfigurable_permissions: {},\n\t\t\t\t};\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post('/2.0/group_memberships', expectedBody)\n\t\t\t\t\t\t.reply(201, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tuserId,\n\t\t\t\t\t\tgroupId,\n\t\t\t\t\t\t'--set-member',\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should add a user to a group with the set-member flag passed (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post('/2.0/group_memberships', expectedBody)\n\t\t\t\t\t\t.reply(201, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tuserId,\n\t\t\t\t\t\tgroupId,\n\t\t\t\t\t\t'--set-member',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should add a user to a group with the set-member flag passed (YAML Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post('/2.0/group_memberships', {\n\t\t\t\t\t\t\t...expectedBody,\n\t\t\t\t\t\t\trole: 'admin',\n\t\t\t\t\t\t\tconfigurable_permissions: {\n\t\t\t\t\t\t\t\tcan_run_reports: true,\n\t\t\t\t\t\t\t\tcan_instant_login: true,\n\t\t\t\t\t\t\t\tcan_create_accounts: true,\n\t\t\t\t\t\t\t\tcan_edit_accounts: true,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(201, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tuserId,\n\t\t\t\t\t\tgroupId,\n\t\t\t\t\t\t'--set-admin',\n\t\t\t\t\t\t'--can-run-reports',\n\t\t\t\t\t\t'--can-instant-login',\n\t\t\t\t\t\t'--can-create-accounts',\n\t\t\t\t\t\t'--can-edit-accounts',\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should send optional permissions params when the permission flags are passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\tleche.withData(\n\t\t\t\t\t{\n\t\t\t\t\t\t'set admin flag': ['--set-admin', { role: 'admin' }],\n\t\t\t\t\t\t'role flag set to admin': [\n\t\t\t\t\t\t\t'--role=admin',\n\t\t\t\t\t\t\t{ role: 'admin' },\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'role flag set to member': [\n\t\t\t\t\t\t\t'--role=member',\n\t\t\t\t\t\t\t{ role: 'member' },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\tfunction (flag, parameters) {\n\t\t\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\t\t\tapi\n\t\t\t\t\t\t\t\t.post('/2.0/group_memberships', {\n\t\t\t\t\t\t\t\t\t...expectedBody,\n\t\t\t\t\t\t\t\t\t...parameters,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.reply(201, fixture)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.stdout()\n\t\t\t\t\t\t\t.command([\n\t\t\t\t\t\t\t\tcommand,\n\t\t\t\t\t\t\t\tuserId,\n\t\t\t\t\t\t\t\tgroupId,\n\t\t\t\t\t\t\t\tflag,\n\t\t\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t\t.it(\n\t\t\t\t\t\t\t\t'should send correct role value when flag is passed',\n\t\t\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tleche.withData(\n\t\t['groups:memberships:update', 'groups:membership:update'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet membershipId = '12345',\n\t\t\t\t\tfixture = getFixture('groups/get_group_memberships_id'),\n\t\t\t\t\tyamlOutput = getFixture(\n\t\t\t\t\t\t'output/groups_membership_update_yaml.txt'\n\t\t\t\t\t);\n\n\t\t\t\tlet expectedBody = {\n\t\t\t\t\trole: 'member',\n\t\t\t\t\tconfigurable_permissions: {},\n\t\t\t\t};\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(\n\t\t\t\t\t\t\t`/2.0/group_memberships/${membershipId}`,\n\t\t\t\t\t\t\texpectedBody\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tmembershipId,\n\t\t\t\t\t\t'--set-member',\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t\"should update a user's membership to a group with the set-member flag passed (JSON Output)\",\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(\n\t\t\t\t\t\t\t`/2.0/group_memberships/${membershipId}`,\n\t\t\t\t\t\t\texpectedBody\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tmembershipId,\n\t\t\t\t\t\t'--set-member',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t\"should update a user's membership to a group with the set-member flag passed (YAML Output)\",\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(`/2.0/group_memberships/${membershipId}`, {\n\t\t\t\t\t\t\t...expectedBody,\n\t\t\t\t\t\t\trole: 'admin',\n\t\t\t\t\t\t\tconfigurable_permissions: {\n\t\t\t\t\t\t\t\tcan_run_reports: true,\n\t\t\t\t\t\t\t\tcan_instant_login: true,\n\t\t\t\t\t\t\t\tcan_create_accounts: true,\n\t\t\t\t\t\t\t\tcan_edit_accounts: true,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tmembershipId,\n\t\t\t\t\t\t'--set-admin',\n\t\t\t\t\t\t'--can-run-reports',\n\t\t\t\t\t\t'--can-instant-login',\n\t\t\t\t\t\t'--can-create-accounts',\n\t\t\t\t\t\t'--can-edit-accounts',\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should send optional permissions params when the permission flags are passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\tleche.withData(\n\t\t\t\t\t{\n\t\t\t\t\t\t'set admin flag': ['--set-admin', { role: 'admin' }],\n\t\t\t\t\t\t'role flag set to admin': [\n\t\t\t\t\t\t\t'--role=admin',\n\t\t\t\t\t\t\t{ role: 'admin' },\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'role flag set to member': [\n\t\t\t\t\t\t\t'--role=member',\n\t\t\t\t\t\t\t{ role: 'member' },\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\tfunction (flag, parameters) {\n\t\t\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\t\t\tapi\n\t\t\t\t\t\t\t\t.put(`/2.0/group_memberships/${membershipId}`, {\n\t\t\t\t\t\t\t\t\t...expectedBody,\n\t\t\t\t\t\t\t\t\t...parameters,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.stdout()\n\t\t\t\t\t\t\t.command([\n\t\t\t\t\t\t\t\tcommand,\n\t\t\t\t\t\t\t\tmembershipId,\n\t\t\t\t\t\t\t\tflag,\n\t\t\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t\t.it(\n\t\t\t\t\t\t\t\t\"should update a user's membership with correct role value when flag is passed\",\n\t\t\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tleche.withData(\n\t\t['groups:memberships:remove', 'groups:membership:remove'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet membershipId = '12345';\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.delete(`/2.0/group_memberships/${membershipId}`)\n\t\t\t\t\t\t.reply(204)\n\t\t\t\t)\n\t\t\t\t\t.stderr()\n\t\t\t\t\t.command([command, membershipId, '--token=test'])\n\t\t\t\t\t.it('should remove a user from a group', (context) => {\n\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t\t`Removed membership ${membershipId}${os.EOL}`\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t});\n\t\t}\n\t);\n\n\tdescribe('groups:terminate-session', function () {\n\t\tlet groupsIDs = ['12345', '67890'];\n\t\tlet fixture = getFixture('groups/post_groups_terminate_sessions');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/groups/terminate_sessions', {\n\t\t\t\t\tgroup_ids: groupsIDs,\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'groups:terminate-session',\n\t\t\t\t'--group-ids',\n\t\t\t\t'12345',\n\t\t\t\t'67890',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should terminate sessions for the specified groups',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/hubs.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst { assert } = require('chai');\nconst os = require('node:os');\nconst { TEST_API_ROOT, getFixture } = require('../helpers/test-helper');\n\ndescribe('Hubs', function () {\n\tdescribe('hubs', function () {\n\t\tconst hubResponse = JSON.parse(getFixture('hubs/get_hubs_id'));\n\t\tconst response = {\n\t\t\tentries: [hubResponse],\n\t\t\tlimit: 10,\n\t\t};\n\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/hubs')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tquery: 'team',\n\t\t\t\t\t\tscope: 'editable',\n\t\t\t\t\t\tsort: 'name',\n\t\t\t\t\t\tdirection: 'ASC',\n\t\t\t\t\t\tlimit: 10,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, response)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'hubs',\n\t\t\t\t'--query=team',\n\t\t\t\t'--scope=editable',\n\t\t\t\t'--sort=name',\n\t\t\t\t'--direction=ASC',\n\t\t\t\t'--max-items=10',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('lists hubs with provided filters', (context) => {\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), response.entries);\n\t\t\t});\n\n\t\tconst firstPageEntries = Array.from({ length: 1000 }, (_, index) => ({\n\t\t\tid: `${index + 1}`,\n\t\t\ttype: 'hubs',\n\t\t}));\n\t\tconst secondPageEntries = [{ id: '1001', type: 'hubs' }];\n\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/hubs')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tquery: 'team',\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, {\n\t\t\t\t\t\tentries: firstPageEntries,\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t\tnext_marker: 'next-page',\n\t\t\t\t\t})\n\t\t\t\t\t.get('/2.0/hubs')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tquery: 'team',\n\t\t\t\t\t\tlimit: 1,\n\t\t\t\t\t\tmarker: 'next-page',\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, {\n\t\t\t\t\t\tentries: secondPageEntries,\n\t\t\t\t\t\tlimit: 1,\n\t\t\t\t\t})\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'hubs',\n\t\t\t\t'--query=team',\n\t\t\t\t'--max-items=1001',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('follows next_marker until max-items is reached', (context) => {\n\t\t\t\tconst output = JSON.parse(context.stdout);\n\t\t\t\tassert.lengthOf(output, 1001);\n\t\t\t\tassert.equal(output[0].id, '1');\n\t\t\t\tassert.equal(output[1000].id, '1001');\n\t\t\t});\n\t});\n\n\tdescribe('hubs:enterprise', function () {\n\t\tconst hubResponse = JSON.parse(getFixture('hubs/get_hubs_id'));\n\t\tconst response = {\n\t\t\tentries: [hubResponse],\n\t\t\tlimit: 50,\n\t\t};\n\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/enterprise_hubs')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tquery: 'enterprise',\n\t\t\t\t\t\tsort: 'updated_at',\n\t\t\t\t\t\tdirection: 'DESC',\n\t\t\t\t\t\tlimit: 50,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, response)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'hubs:enterprise',\n\t\t\t\t'--query=enterprise',\n\t\t\t\t'--sort=updated_at',\n\t\t\t\t'--direction=DESC',\n\t\t\t\t'--max-items=50',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('lists enterprise hubs with provided filters', (context) => {\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), response.entries);\n\t\t\t});\n\t});\n\n\tdescribe('hubs:items', function () {\n\t\tconst response = JSON.parse(getFixture('hubs/get_hub_items'));\n\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/hub_items')\n\t\t\t\t\t.query({\n\t\t\t\t\t\thub_id: '12345',\n\t\t\t\t\t\tparent_id: '67890',\n\t\t\t\t\t\tlimit: 2,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, response)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'hubs:items',\n\t\t\t\t'12345',\n\t\t\t\t'--parent-id=67890',\n\t\t\t\t'--max-items=2',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('lists items in a hub', (context) => {\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), response.entries);\n\t\t\t});\n\t});\n\n\tdescribe('hubs:items:manage', function () {\n\t\tconst response = JSON.parse(getFixture('hubs/post_hubs_id_manage_items'));\n\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.post('/2.0/hubs/12345/manage_items', {\n\t\t\t\t\t\toperations: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\taction: 'add',\n\t\t\t\t\t\t\t\titem: {\n\t\t\t\t\t\t\t\t\tid: '11111',\n\t\t\t\t\t\t\t\t\ttype: 'file',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tparent_id: '67890',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\taction: 'remove',\n\t\t\t\t\t\t\t\titem: {\n\t\t\t\t\t\t\t\t\tid: '22222',\n\t\t\t\t\t\t\t\t\ttype: 'folder',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, response)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'hubs:items:manage',\n\t\t\t\t'12345',\n\t\t\t\t'--add=id=11111,type=file,parent-id=67890',\n\t\t\t\t'--remove=id=22222,type=folder',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('adds and removes items in a hub', (context) => {\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), response);\n\t\t\t});\n\t});\n\n\tdescribe('hubs:document:pages', function () {\n\t\tconst response = JSON.parse(getFixture('hubs/get_hub_document_pages'));\n\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/hub_document_pages')\n\t\t\t\t\t.query({\n\t\t\t\t\t\thub_id: '12345',\n\t\t\t\t\t\tlimit: 2,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, response)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'hubs:document:pages',\n\t\t\t\t'12345',\n\t\t\t\t'--max-items=2',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('lists hub document pages', (context) => {\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), response.entries);\n\t\t\t});\n\t});\n\n\tdescribe('hubs:document:blocks', function () {\n\t\tconst response = JSON.parse(getFixture('hubs/get_hub_document_blocks'));\n\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/hub_document_blocks')\n\t\t\t\t\t.query({\n\t\t\t\t\t\thub_id: '12345',\n\t\t\t\t\t\tpage_id: 'page_1',\n\t\t\t\t\t\tlimit: 2,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, response)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'hubs:document:blocks',\n\t\t\t\t'12345',\n\t\t\t\t'page_1',\n\t\t\t\t'--max-items=2',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('lists hub document blocks for a page', (context) => {\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), response.entries);\n\t\t\t});\n\t});\n\n\tdescribe('hubs:get', function () {\n\t\tconst response = JSON.parse(getFixture('hubs/get_hubs_id'));\n\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi.get('/2.0/hubs/12345').reply(200, response)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['hubs:get', '12345', '--json', '--token=test'])\n\t\t\t.it('gets a hub by ID', (context) => {\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), response);\n\t\t\t});\n\t});\n\n\tdescribe('hubs:create', function () {\n\t\tconst response = {\n\t\t\tid: '98765',\n\t\t\ttype: 'hubs',\n\t\t\ttitle: 'New Hub',\n\t\t\tdescription: 'New hub description',\n\t\t};\n\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.post('/2.0/hubs', {\n\t\t\t\t\t\ttitle: 'New Hub',\n\t\t\t\t\t\tdescription: 'New hub description',\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, response)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'hubs:create',\n\t\t\t\t'New Hub',\n\t\t\t\t'--description=New hub description',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('creates a hub with title and description', (context) => {\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), {\n\t\t\t\t\tid: '98765',\n\t\t\t\t\ttype: 'hubs',\n\t\t\t\t\ttitle: 'New Hub',\n\t\t\t\t\tdescription: 'New hub description',\n\t\t\t\t});\n\t\t\t});\n\t});\n\n\tdescribe('hubs:update', function () {\n\t\tconst response = JSON.parse(getFixture('hubs/put_hubs_id'));\n\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.put('/2.0/hubs/12345', {\n\t\t\t\t\t\ttitle: 'Updated Hub',\n\t\t\t\t\t\tdescription: 'Updated description',\n\t\t\t\t\t\tis_ai_enabled: true,\n\t\t\t\t\t\tis_collaboration_restricted_to_enterprise: true,\n\t\t\t\t\t\tcan_non_owners_invite: true,\n\t\t\t\t\t\tcan_shared_link_be_created: false,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, response)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'hubs:update',\n\t\t\t\t'12345',\n\t\t\t\t'--title=Updated Hub',\n\t\t\t\t'--description=Updated description',\n\t\t\t\t'--ai-enabled',\n\t\t\t\t'--collaboration-restricted-to-enterprise',\n\t\t\t\t'--can-non-owners-invite',\n\t\t\t\t'--no-can-shared-link-be-created',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('updates a hub with provided fields', (context) => {\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), response);\n\t\t\t});\n\t});\n\n\tdescribe('hubs:copy', function () {\n\t\tconst response = {\n\t\t\tid: '55555',\n\t\t\ttype: 'hubs',\n\t\t\ttitle: 'Copied Hub',\n\t\t\tdescription: 'Copied description',\n\t\t};\n\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.post('/2.0/hubs/12345/copy', {\n\t\t\t\t\t\ttitle: 'Copied Hub',\n\t\t\t\t\t\tdescription: 'Copied description',\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, response)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'hubs:copy',\n\t\t\t\t'12345',\n\t\t\t\t'--title=Copied Hub',\n\t\t\t\t'--description=Copied description',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('copies a hub with overrides', (context) => {\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), {\n\t\t\t\t\tid: '55555',\n\t\t\t\t\ttype: 'hubs',\n\t\t\t\t\ttitle: 'Copied Hub',\n\t\t\t\t\tdescription: 'Copied description',\n\t\t\t\t});\n\t\t\t});\n\t});\n\n\tdescribe('hubs:delete', function () {\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi.delete('/2.0/hubs/12345').reply(204)\n\t\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['hubs:delete', '12345', '--token=test'])\n\t\t\t.it('deletes a hub by ID', (context) => {\n\t\t\t\tassert.equal(context.stderr, `Deleted hub 12345${os.EOL}`);\n\t\t\t});\n\t});\n\n\tdescribe('hubs:collaborations', function () {\n\t\tconst response = JSON.parse(getFixture('hubs/get_hub_collaborations'));\n\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/hub_collaborations')\n\t\t\t\t\t.query({\n\t\t\t\t\t\thub_id: '12345',\n\t\t\t\t\t\tlimit: 1,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, response)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'hubs:collaborations',\n\t\t\t\t'12345',\n\t\t\t\t'--max-items=1',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('lists collaborations for a hub', (context) => {\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), response.entries);\n\t\t\t});\n\t});\n\n\tdescribe('hubs:collaborations:create', function () {\n\t\tconst response = JSON.parse(getFixture('hubs/post_hub_collaborations'));\n\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.post('/2.0/hub_collaborations', {\n\t\t\t\t\t\thub: {\n\t\t\t\t\t\t\tid: '12345',\n\t\t\t\t\t\t\ttype: 'hubs',\n\t\t\t\t\t\t},\n\t\t\t\t\t\taccessible_by: {\n\t\t\t\t\t\t\ttype: 'user',\n\t\t\t\t\t\t\tid: '22222',\n\t\t\t\t\t\t},\n\t\t\t\t\t\trole: 'editor',\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, response)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'hubs:collaborations:create',\n\t\t\t\t'12345',\n\t\t\t\t'--role=editor',\n\t\t\t\t'--user-id=22222',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('creates a collaboration for a hub', (context) => {\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), response);\n\t\t\t});\n\n\t\tit('rejects unsupported hub collaboration roles on create', async function () {\n\t\t\treturn test\n\t\t\t\t.command([\n\t\t\t\t\t'hubs:collaborations:create',\n\t\t\t\t\t'12345',\n\t\t\t\t\t'--role=owner',\n\t\t\t\t\t'--user-id=22222',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\terror.message,\n\t\t\t\t\t\t'Expected --role=owner to be one of: editor, viewer, co-owner'\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('hubs:collaborations:get', function () {\n\t\tconst response = JSON.parse(getFixture('hubs/get_hub_collaborations_id'));\n\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi.get('/2.0/hub_collaborations/99999').reply(200, response)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'hubs:collaborations:get',\n\t\t\t\t'99999',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('gets a hub collaboration by ID', (context) => {\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), response);\n\t\t\t});\n\t});\n\n\tdescribe('hubs:collaborations:update', function () {\n\t\tconst response = JSON.parse(\n\t\t\tgetFixture('hubs/put_hub_collaborations_id')\n\t\t);\n\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.put('/2.0/hub_collaborations/99999', {\n\t\t\t\t\t\trole: 'viewer',\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, response)\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'hubs:collaborations:update',\n\t\t\t\t'99999',\n\t\t\t\t'--role=viewer',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('updates a hub collaboration role', (context) => {\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), response);\n\t\t\t});\n\n\t\tit('rejects unsupported hub collaboration roles on update', async function () {\n\t\t\treturn test\n\t\t\t\t.command([\n\t\t\t\t\t'hubs:collaborations:update',\n\t\t\t\t\t'99999',\n\t\t\t\t\t'--role=owner',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\terror.message,\n\t\t\t\t\t\t'Expected --role=owner to be one of: editor, viewer, co-owner'\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('hubs:collaborations:delete', function () {\n\t\ttest\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi.delete('/2.0/hub_collaborations/99999').reply(204)\n\t\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['hubs:collaborations:delete', '99999', '--token=test'])\n\t\t\t.it('deletes a hub collaboration by ID', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Deleted hub collaboration 99999${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/commands/integration-mappings.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\n\ndescribe('Integration Mappings', function () {\n\tdescribe('integration-mappings:slack:list', function () {\n\t\tlet partnerItemId = '1234',\n\t\t\tfixture = getFixture(\n\t\t\t\t'integration-mappings/get_integration_mappings_slack_page_1'\n\t\t\t),\n\t\t\tfixture2 = getFixture(\n\t\t\t\t'integration-mappings/get_integration_mappings_slack_page_2'\n\t\t\t),\n\t\t\tjsonOutput = getFixture(\n\t\t\t\t'output/integration_mappings_slack_get_json.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/integration_mappings/slack')\n\t\t\t\t.query({\n\t\t\t\t\tpartner_item_id: partnerItemId,\n\t\t\t\t\tis_manually_created: true,\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/integration_mappings/slack')\n\t\t\t\t.query({\n\t\t\t\t\tpartner_item_id: partnerItemId,\n\t\t\t\t\tis_manually_created: true,\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t\tmarker: 'ZDFARAFD',\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'integration-mappings:slack:list',\n\t\t\t\t`--partner-item-id=${partnerItemId}`,\n\t\t\t\t'--manually-created',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should list Slack integration mappings', (context) => {\n\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t});\n\t});\n\n\tdescribe('integration-mappings:slack:create', function () {\n\t\tlet boxItemId = '23456',\n\t\t\tchannelId = 'C12378991223',\n\t\t\tslackOrgId = 'E1234567',\n\t\t\tfixture = getFixture(\n\t\t\t\t'integration-mappings/post_integration_mappings_slack'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/integration_mappings/slack', {\n\t\t\t\t\tbox_item: {\n\t\t\t\t\t\tid: boxItemId,\n\t\t\t\t\t\ttype: 'folder',\n\t\t\t\t\t},\n\t\t\t\t\tpartner_item: {\n\t\t\t\t\t\ttype: 'channel',\n\t\t\t\t\t\tid: channelId,\n\t\t\t\t\t\tslack_org_id: slackOrgId,\n\t\t\t\t\t},\n\t\t\t\t\toptions: {\n\t\t\t\t\t\tis_access_management_disabled: true,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'integration-mappings:slack:create',\n\t\t\t\tboxItemId,\n\t\t\t\tchannelId,\n\t\t\t\t`--slack-org-id=${slackOrgId}`,\n\t\t\t\t'--disable-access-management',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should create a Slack integration mapping', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\t});\n\n\tdescribe('integration-mappings:slack:update', function () {\n\t\tlet integrationMappingId = '12345',\n\t\t\tboxItemId = '7890',\n\t\t\tfixture = getFixture(\n\t\t\t\t'integration-mappings/put_integration_mappings_slack_id'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(\n\t\t\t\t\t`/2.0/integration_mappings/slack/${integrationMappingId}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tbox_item: {\n\t\t\t\t\t\t\tid: boxItemId,\n\t\t\t\t\t\t\ttype: 'folder',\n\t\t\t\t\t\t},\n\t\t\t\t\t\toptions: {\n\t\t\t\t\t\t\tis_access_management_disabled: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'integration-mappings:slack:update',\n\t\t\t\tintegrationMappingId,\n\t\t\t\t`--box-item-id=${boxItemId}`,\n\t\t\t\t'--no-disable-access-management',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should update a Slack integration mapping', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\t});\n\n\tdescribe('integration-mappings:slack:delete', function () {\n\t\tlet integrationMappingId = '12345';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(\n\t\t\t\t\t`/2.0/integration_mappings/slack/${integrationMappingId}`\n\t\t\t\t)\n\t\t\t\t.reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'integration-mappings:slack:delete',\n\t\t\t\tintegrationMappingId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should delete a Slack integration mapping', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Deleted Slack integration mapping ${integrationMappingId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tdescribe('integration-mappings:teams:list', function () {\n\t\tlet partnerItemId = '1234',\n\t\t\tpartnerItemType = 'channel',\n\t\t\tboxItemId = '1234',\n\t\t\tboxItemType = 'folder',\n\t\t\tfixture = getFixture(\n\t\t\t\t'integration-mappings/get_integration_mappings_teams'\n\t\t\t),\n\t\t\texpectedResult = {\n\t\t\t\tentries: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: '12345',\n\t\t\t\t\t\ttype: 'integration_mapping',\n\t\t\t\t\t\tboxItem: {\n\t\t\t\t\t\t\tid: '42037322',\n\t\t\t\t\t\t\ttype: 'folder',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcreatedAt: {\n\t\t\t\t\t\t\tvalue: '2012-12-12T18:53:43.000Z',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tintegrationType: 'teams',\n\t\t\t\t\t\tisOverriddenByManualMapping: true,\n\t\t\t\t\t\tmodifiedAt: {\n\t\t\t\t\t\t\tvalue: '2012-12-12T18:53:43.000Z',\n\t\t\t\t\t\t},\n\t\t\t\t\t\tpartnerItem: {\n\t\t\t\t\t\t\tid: '19%3ABCD-Avgfggkggyftdtfgghjhkhkhh%40thread:tacv2',\n\t\t\t\t\t\t\ttenantId: 'E1234567',\n\t\t\t\t\t\t\ttype: 'channel',\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/integration_mappings/teams')\n\t\t\t\t.query({\n\t\t\t\t\tpartner_item_id: partnerItemId,\n\t\t\t\t\tpartner_item_type: partnerItemType,\n\t\t\t\t\tbox_item_id: boxItemId,\n\t\t\t\t\tbox_item_type: boxItemType,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture, {\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t})\n\t\t)\n\t\t\t.stderr()\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'integration-mappings:teams:list',\n\t\t\t\t`--partner-item-id=${partnerItemId}`,\n\t\t\t\t`--partner-item-type=${partnerItemType}`,\n\t\t\t\t`--box-item-id=${boxItemId}`,\n\t\t\t\t`--box-item-type=${boxItemType}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should list Teams integration mappings', (context) => {\n\t\t\t\tassert.equal(context.stderr, '');\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), expectedResult);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/integration_mappings/teams')\n\t\t\t\t.query({\n\t\t\t\t\tpartner_item_id: partnerItemId,\n\t\t\t\t\tpartner_item_type: partnerItemType,\n\t\t\t\t\tbox_item_id: boxItemId,\n\t\t\t\t\tbox_item_type: boxItemType,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture, {\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t})\n\t\t)\n\t\t\t.stderr()\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'integration-mappings:teams:list',\n\t\t\t\t`--partner-item-id=${partnerItemId}`,\n\t\t\t\t`--partner-item-type=${partnerItemType}`,\n\t\t\t\t`--box-item-id=${boxItemId}`,\n\t\t\t\t`--box-item-type=${boxItemType}`,\n\t\t\t\t'--raw-json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should list Teams integration mappings using raw JSON output',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stderr, '');\n\t\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), JSON.parse(fixture));\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('integration-mappings:teams:create', function () {\n\t\tlet partnerItemId = '1234',\n\t\t\tpartnerItemType = 'channel',\n\t\t\tboxItemId = '1234',\n\t\t\tpartnerItemTeamId = 'hjgjgjg-bhhj-564a-b643-hghgj685u',\n\t\t\tpartnerItemTenantId = 'E1234567',\n\t\t\tfixture = getFixture(\n\t\t\t\t'integration-mappings/post_integration_mappings_teams'\n\t\t\t),\n\t\t\texpectedResult = {\n\t\t\t\tid: '12345',\n\t\t\t\ttype: 'integration_mapping',\n\t\t\t\tboxItem: {\n\t\t\t\t\tid: '42037322',\n\t\t\t\t\ttype: 'folder',\n\t\t\t\t},\n\t\t\t\tcreatedAt: {\n\t\t\t\t\tvalue: '2012-12-12T18:53:43.000Z',\n\t\t\t\t},\n\t\t\t\tintegrationType: 'teams',\n\t\t\t\tisOverriddenByManualMapping: true,\n\t\t\t\tmodifiedAt: {\n\t\t\t\t\tvalue: '2012-12-12T18:53:43.000Z',\n\t\t\t\t},\n\t\t\t\tpartnerItem: {\n\t\t\t\t\tid: '19%3ABCD-Avgfggkggyftdtfgghjhkhkhh%40thread:tacv2',\n\t\t\t\t\ttenantId: 'E1234567',\n\t\t\t\t\ttype: 'channel',\n\t\t\t\t},\n\t\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/integration_mappings/teams', {\n\t\t\t\t\tpartner_item: {\n\t\t\t\t\t\ttype: 'channel',\n\t\t\t\t\t\tid: partnerItemId,\n\t\t\t\t\t\ttenant_id: 'E1234567',\n\t\t\t\t\t\tteam_id: partnerItemTeamId,\n\t\t\t\t\t},\n\t\t\t\t\tbox_item: {\n\t\t\t\t\t\ttype: 'folder',\n\t\t\t\t\t\tid: boxItemId,\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture, {\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t})\n\t\t)\n\t\t\t.stderr()\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'integration-mappings:teams:create',\n\t\t\t\tboxItemId,\n\t\t\t\tpartnerItemId,\n\t\t\t\tpartnerItemType,\n\t\t\t\tpartnerItemTeamId,\n\t\t\t\tpartnerItemTenantId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should create a Teams integration mapping', (context) => {\n\t\t\t\tassert.equal(context.stderr, '');\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), expectedResult);\n\t\t\t});\n\t});\n\n\tdescribe('integration-mappings:teams:update', function () {\n\t\tlet integrationMappingId = '12345',\n\t\t\tboxItemId = '7890',\n\t\t\tfixture = getFixture(\n\t\t\t\t'integration-mappings/put_integration_mappings_teams_id'\n\t\t\t),\n\t\t\texpectedResult = {\n\t\t\t\tid: '12345',\n\t\t\t\ttype: 'integration_mapping',\n\t\t\t\tboxItem: {\n\t\t\t\t\tid: '7890',\n\t\t\t\t\ttype: 'folder',\n\t\t\t\t},\n\t\t\t\tcreatedAt: {\n\t\t\t\t\tvalue: '2012-12-12T18:53:43.000Z',\n\t\t\t\t},\n\t\t\t\tintegrationType: 'teams',\n\t\t\t\tisOverriddenByManualMapping: true,\n\t\t\t\tmodifiedAt: {\n\t\t\t\t\tvalue: '2012-12-12T18:53:43.000Z',\n\t\t\t\t},\n\t\t\t\tpartnerItem: {\n\t\t\t\t\tid: '19%3ABCD-Avgfggkggyftdtfgghjhkhkhh%40thread:tacv2',\n\t\t\t\t\ttenantId: 'E1234567',\n\t\t\t\t\ttype: 'channel',\n\t\t\t\t},\n\t\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(\n\t\t\t\t\t`/2.0/integration_mappings/teams/${integrationMappingId}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tbox_item: {\n\t\t\t\t\t\t\tid: boxItemId,\n\t\t\t\t\t\t\ttype: 'folder',\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t\t.reply(200, fixture, {\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t})\n\t\t)\n\t\t\t.stderr()\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'integration-mappings:teams:update',\n\t\t\t\tintegrationMappingId,\n\t\t\t\t`--box-item-id=${boxItemId}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should update a Teams integration mapping', (context) => {\n\t\t\t\tassert.equal(context.stderr, '');\n\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), expectedResult);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(\n\t\t\t\t\t`/2.0/integration_mappings/teams/${integrationMappingId}`,\n\t\t\t\t\t{\n\t\t\t\t\t\tbox_item: {\n\t\t\t\t\t\t\tid: boxItemId,\n\t\t\t\t\t\t\ttype: 'folder',\n\t\t\t\t\t\t},\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t\t.reply(200, fixture, {\n\t\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t})\n\t\t)\n\t\t\t.stderr()\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'integration-mappings:teams:update',\n\t\t\t\tintegrationMappingId,\n\t\t\t\t`--box-item-id=${boxItemId}`,\n\t\t\t\t'--raw-json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a Teams integration mapping using raw JSON output',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stderr, '');\n\t\t\t\t\tassert.deepEqual(JSON.parse(context.stdout), JSON.parse(fixture));\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('integration-mappings:teams:delete', function () {\n\t\tlet integrationMappingId = '12345';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(\n\t\t\t\t\t`/2.0/integration_mappings/teams/${integrationMappingId}`\n\t\t\t\t)\n\t\t\t\t.reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'integration-mappings:teams:delete',\n\t\t\t\tintegrationMappingId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should delete a Teams integration mapping', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Deleted Teams integration mapping ${integrationMappingId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/commands/legal-hold-policies.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\n\ndescribe('Legal Hold Policies', function () {\n\tdescribe('legal-hold-policies:get', function () {\n\t\tlet policyId = '11111',\n\t\t\tfixture = getFixture(\n\t\t\t\t'legal-hold-policies/get_legal_hold_policies_id'\n\t\t\t),\n\t\t\tyamlOutput = getFixture('output/legal_hold_policies_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/legal_hold_policies/${policyId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:get',\n\t\t\t\tpolicyId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information about a legal hold policy (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/legal_hold_policies/${policyId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['legal-hold-policies:get', policyId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a legal hold policy (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/legal_hold_policies/${policyId}`)\n\t\t\t\t.query({ fields: 'id' })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:get',\n\t\t\t\tpolicyId,\n\t\t\t\t'--fields=id',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('legal-hold-policies:create', function () {\n\t\tlet name = 'Trial Documents',\n\t\t\tdescription = 'Documents for the litigation proceedings',\n\t\t\tstartDate = '2011-08-14T05:11:00+00:00',\n\t\t\tendDate = '2014-08-14T05:11:00+00:00',\n\t\t\tfixture = getFixture(\n\t\t\t\t'legal-hold-policies/post_legal_hold_policies'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/legal_hold_policies_create_yaml.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/legal_hold_policies', {\n\t\t\t\t\tpolicy_name: name,\n\t\t\t\t\tis_ongoing: true,\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:create',\n\t\t\t\tname,\n\t\t\t\t'--ongoing',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a new legal hold policy with the is-ongoing flag passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/legal_hold_policies', {\n\t\t\t\t\tpolicy_name: name,\n\t\t\t\t\tis_ongoing: true,\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:create',\n\t\t\t\tname,\n\t\t\t\t'--ongoing',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a new legal hold policy with the is-ongoing flag passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/legal_hold_policies', {\n\t\t\t\t\tpolicy_name: name,\n\t\t\t\t\tdescription,\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:create',\n\t\t\t\tname,\n\t\t\t\t`--description=${description}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send the description param when the --description flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/legal_hold_policies', {\n\t\t\t\t\tpolicy_name: name,\n\t\t\t\t\tfilter_started_at: startDate,\n\t\t\t\t\tfilter_ended_at: endDate,\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:create',\n\t\t\t\tname,\n\t\t\t\t`--filter-started-at=${startDate}`,\n\t\t\t\t`--filter-ended-at=${endDate}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send the filter start and end dates when the --filter-*-at flags are passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('legal-hold-polices:update', function () {\n\t\tlet policyId = '11111',\n\t\t\tdescription = 'Documents related to our ongoing litigation',\n\t\t\tname = '[DONE] Trial documents',\n\t\t\treleaseNotes = 'The trial concluded with favorable results',\n\t\t\tfixture = getFixture(\n\t\t\t\t'legal-hold-policies/put_legal_hold_policies_id'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/legal_hold_policies_update_yaml.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/legal_hold_policies/${policyId}`, { description })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:update',\n\t\t\t\tpolicyId,\n\t\t\t\t`--description=${description}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a legal hold policy with the description flag passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/legal_hold_policies/${policyId}`, { description })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:update',\n\t\t\t\tpolicyId,\n\t\t\t\t`--description=${description}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a legal hold policy with the description flag passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/legal_hold_policies/${policyId}`, {\n\t\t\t\t\tpolicy_name: name,\n\t\t\t\t\trelease_notes: releaseNotes,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:update',\n\t\t\t\tpolicyId,\n\t\t\t\t`--policy-name=${name}`,\n\t\t\t\t`--release-notes=${releaseNotes}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a legal hold policy with the --policy-name and --release-notes flags passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('legal-hold-policies:delete', function () {\n\t\tlet policyId = '11111';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.delete(`/2.0/legal_hold_policies/${policyId}`).reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['legal-hold-policies:delete', policyId, '--token=test'])\n\t\t\t.it('should delete a legal hold policy', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Deleted legal hold policy ${policyId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tdescribe('legal-hold-policies', function () {\n\t\tlet fixture = getFixture('legal-hold-policies/get_legal_hold_policies'),\n\t\t\tpolicyNameFilter = 'Trial',\n\t\t\tjsonOutput = getFixture('output/legal_hold_policies_list_json.txt'),\n\t\t\ttableOutput = getFixture(\n\t\t\t\t'output/legal_hold_policies_list_table.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/legal_hold_policies')\n\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['legal-hold-policies', '--json', '--token=test'])\n\t\t\t.it('should list legal hold policies (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/legal_hold_policies')\n\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['legal-hold-policies', '--token=test'])\n\t\t\t.it('should list legal hold policies (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, tableOutput);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/legal_hold_policies')\n\t\t\t\t.query({ policy_name: policyNameFilter, limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies',\n\t\t\t\t`--policy-name=${policyNameFilter}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send policy name filter when --policy-name flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/legal_hold_policies')\n\t\t\t\t.query({ fields: 'id', limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies',\n\t\t\t\t'--fields=id',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('legal-hold-policies:assignments', function () {\n\t\tlet policyId = '11111',\n\t\t\tassignToType = 'file',\n\t\t\tassignToID = '99',\n\t\t\tfixture = getFixture(\n\t\t\t\t'legal-hold-policies/get_legal_hold_policy_assignments_policy_id_page_1'\n\t\t\t),\n\t\t\tfixture2 = getFixture(\n\t\t\t\t'legal-hold-policies/get_legal_hold_policy_assignments_policy_id_page_2'\n\t\t\t),\n\t\t\tjsonOutput = getFixture(\n\t\t\t\t'output/legal_hold_policies_list_assignments_json.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/legal_hold_policy_assignments')\n\t\t\t\t.query({\n\t\t\t\t\tpolicy_id: policyId,\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/legal_hold_policy_assignments')\n\t\t\t\t.query({\n\t\t\t\t\tpolicy_id: policyId,\n\t\t\t\t\tmarker: 'ZDCE3',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:assignments',\n\t\t\t\tpolicyId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should list policy assignments (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/legal_hold_policy_assignments')\n\t\t\t\t.query({\n\t\t\t\t\tpolicy_id: policyId,\n\t\t\t\t\tassign_to_type: assignToType,\n\t\t\t\t\tassign_to_id: assignToID,\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/legal_hold_policy_assignments')\n\t\t\t\t.query({\n\t\t\t\t\tpolicy_id: policyId,\n\t\t\t\t\tassign_to_type: assignToType,\n\t\t\t\t\tassign_to_id: assignToID,\n\t\t\t\t\tmarker: 'ZDCE3',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:assignments',\n\t\t\t\tpolicyId,\n\t\t\t\t`--assign-to-type=${assignToType}`,\n\t\t\t\t`--assign-to-id=${assignToID}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send assignment filter params when --assign-to-* flags are passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/legal_hold_policy_assignments')\n\t\t\t\t.query({\n\t\t\t\t\tfields: 'id',\n\t\t\t\t\tpolicy_id: policyId,\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/legal_hold_policy_assignments')\n\t\t\t\t.query({\n\t\t\t\t\tfields: 'id',\n\t\t\t\t\tpolicy_id: policyId,\n\t\t\t\t\tmarker: 'ZDCE3',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:assignments',\n\t\t\t\tpolicyId,\n\t\t\t\t'--fields=id',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('legal-hold-policies:assignments:get', function () {\n\t\tlet assignmentId = '12345',\n\t\t\tfixture = getFixture(\n\t\t\t\t'legal-hold-policies/get_legal_hold_policy_assignments_id'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/legal_hold_policies_get_assignment_yaml.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/legal_hold_policy_assignments/${assignmentId}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:assignments:get',\n\t\t\t\tassignmentId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information about a policy assignment (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/legal_hold_policy_assignments/${assignmentId}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:assignments:get',\n\t\t\t\tassignmentId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information about a policy assignment (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/legal_hold_policy_assignments/${assignmentId}`)\n\t\t\t\t.query({ fields: 'id' })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:assignments:get',\n\t\t\t\tassignmentId,\n\t\t\t\t'--fields=id',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('legal-hold-policies:assign', function () {\n\t\tlet policyId = '11111',\n\t\t\ttype = 'folder',\n\t\t\tfolderId = '55555',\n\t\t\tfixture = getFixture(\n\t\t\t\t'legal-hold-policies/post_legal_hold_policy_assignments'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/legal_hold_policies_assign_yaml.txt'\n\t\t\t);\n\n\t\tlet expectedBody = {\n\t\t\tpolicy_id: policyId,\n\t\t\tassign_to: {\n\t\t\t\ttype: 'folder',\n\t\t\t\tid: folderId,\n\t\t\t},\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/legal_hold_policy_assignments', expectedBody)\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:assign',\n\t\t\t\tpolicyId,\n\t\t\t\t`--assign-to-type=${type}`,\n\t\t\t\t`--assign-to-id=${folderId}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a new policy assignment (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/legal_hold_policy_assignments', expectedBody)\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:assign',\n\t\t\t\tpolicyId,\n\t\t\t\t`--assign-to-type=${type}`,\n\t\t\t\t`--assign-to-id=${folderId}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a new policy assignment (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('legal-hold-policies:assignments:delete', function () {\n\t\tlet assignmentId = '12345';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(`/2.0/legal_hold_policy_assignments/${assignmentId}`)\n\t\t\t\t.reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:assignments:delete',\n\t\t\t\tassignmentId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should delete a policy assignment', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Delete policy assignment ${assignmentId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tdescribe('legal-hold-policies:file-version-holds:get', function () {\n\t\tlet holdId = '99999',\n\t\t\tfixture = getFixture(\n\t\t\t\t'legal-hold-policies/get_file_version_legal_holds_id'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/legal_hold_policies_get_version_hold_yaml.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/file_version_legal_holds/${holdId}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:file-version-holds:get',\n\t\t\t\tholdId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information about a file version legal hold (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/file_version_legal_holds/${holdId}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:file-version-holds:get',\n\t\t\t\tholdId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information about a file version legal hold (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/file_version_legal_holds/${holdId}`)\n\t\t\t\t.query({ fields: 'id' })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:file-version-holds:get',\n\t\t\t\tholdId,\n\t\t\t\t'--fields=id',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('legal-hold-policies:file-version-holds', function () {\n\t\tlet policyId = '11111',\n\t\t\tfixture = getFixture(\n\t\t\t\t'legal-hold-policies/get_file_version_legal_holds_page_1'\n\t\t\t),\n\t\t\tfixture2 = getFixture(\n\t\t\t\t'legal-hold-policies/get_file_version_legal_holds_page_2'\n\t\t\t),\n\t\t\tjsonOutput = getFixture(\n\t\t\t\t'output/legal_hold_policies_list_version_holds_json.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/file_version_legal_holds')\n\t\t\t\t.query({\n\t\t\t\t\tpolicy_id: policyId,\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/file_version_legal_holds')\n\t\t\t\t.query({\n\t\t\t\t\tpolicy_id: policyId,\n\t\t\t\t\tmarker: 'ZDCE3',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:file-version-holds',\n\t\t\t\tpolicyId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should list file version legal holds for a legal hold policy (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/file_version_legal_holds')\n\t\t\t\t.query({\n\t\t\t\t\tfields: 'id',\n\t\t\t\t\tpolicy_id: policyId,\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/file_version_legal_holds')\n\t\t\t\t.query({\n\t\t\t\t\tfields: 'id',\n\t\t\t\t\tpolicy_id: policyId,\n\t\t\t\t\tmarker: 'ZDCE3',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'legal-hold-policies:file-version-holds',\n\t\t\t\tpolicyId,\n\t\t\t\t'--fields=id',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/login.test.js",
    "content": "'use strict';\n\nconst { assert } = require('chai');\nconst sinon = require('sinon');\nconst inquirer = require('inquirer');\nconst nodeHttp = require('node:http');\nconst { test } = require('@oclif/test');\nconst BoxCommand = require('../../src/box-command');\nconst {\n\tassertValidOAuthCode,\n\tgetTokenInfoByAuthCode,\n} = require('../../src/login-helper');\nconst OAuthLoginCommand = require('../../src/commands/login');\n\n// Send a single callback request once the test decides flow timing.\n// Keeping this as a tiny helper makes callback assertions easier to read.\nfunction sendCallback(url) {\n\treturn new Promise((resolve, reject) => {\n\t\tconst request = nodeHttp.get(url, (response) => {\n\t\t\tresponse.resume();\n\t\t\tresolve(response.statusCode);\n\t\t});\n\t\trequest.on('error', reject);\n\t});\n}\n\n// Wait until loopback port accepts connections before sending callback.\n// HTTP status does not matter here; a non-ECONNREFUSED response means server is ready.\nasync function waitForLoopbackPort(port, maxAttempts = 20, delayMs = 5) {\n\tfor (let attempt = 0; attempt < maxAttempts; attempt += 1) {\n\t\ttry {\n\t\t\tawait new Promise((resolve, reject) => {\n\t\t\t\tconst request = nodeHttp.get(\n\t\t\t\t\t`http://localhost:${port}/`,\n\t\t\t\t\t(response) => {\n\t\t\t\t\t\tresponse.resume();\n\t\t\t\t\t\tresolve();\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t\trequest.on('error', reject);\n\t\t\t});\n\t\t\treturn;\n\t\t} catch {\n\t\t\tawait new Promise((resolve) => setTimeout(resolve, delayMs));\n\t\t}\n\t}\n\n\tthrow new Error(\n\t\t`Local callback server on port ${port} did not become ready in time`\n\t);\n}\n\ndescribe('Login', function () {\n\tlet sandbox;\n\tconst DEFAULT_CLIENT_ID = 'udz8zp4yue87uk9dzq4xk425kkwvqvh1';\n\tconst DEFAULT_CLIENT_SECRET = 'iZ1MbvC3ZaF25nbJli7IsKdRHAxfu3fn';\n\n\tbeforeEach(function () {\n\t\tsandbox = sinon.createSandbox();\n\t});\n\n\tafterEach(function () {\n\t\tOAuthLoginCommand._test.resetOAuthCallbackTimeoutMs();\n\t\tOAuthLoginCommand._test.resetOpenAuthorizeInBrowser();\n\t\tsandbox.restore();\n\t});\n\n\tdescribe('getTokenInfoByAuthCode', function () {\n\t\tit('should exchange auth code with optional code_verifier and redirect_uri', async function () {\n\t\t\tconst tokenInfo = {\n\t\t\t\taccessToken: 'test-access-token',\n\t\t\t\trefreshToken: 'test-refresh-token',\n\t\t\t\taccessTokenTTLMS: 3_600_000,\n\t\t\t\tacquiredAtMS: 1,\n\t\t\t};\n\t\t\tconst getTokensStub = sandbox.stub().resolves(tokenInfo);\n\t\t\tconst sdk = {\n\t\t\t\ttokenManager: {\n\t\t\t\t\tgetTokens: getTokensStub,\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst result = await getTokenInfoByAuthCode(\n\t\t\t\tsdk,\n\t\t\t\t'auth-code',\n\t\t\t\t'http://localhost:3000/callback',\n\t\t\t\t'pkce-verifier'\n\t\t\t);\n\n\t\t\tassert.strictEqual(result, tokenInfo);\n\t\t\tassert.isTrue(getTokensStub.calledOnce);\n\t\t\tassert.deepEqual(getTokensStub.firstCall.args[0], {\n\t\t\t\tgrant_type: 'authorization_code',\n\t\t\t\tcode: 'auth-code',\n\t\t\t\tredirect_uri: 'http://localhost:3000/callback',\n\t\t\t\tcode_verifier: 'pkce-verifier',\n\t\t\t});\n\t\t\tassert.isNull(getTokensStub.firstCall.args[1]);\n\t\t});\n\n\t\tit('should exchange auth code without code_verifier', async function () {\n\t\t\tconst tokenInfo = {\n\t\t\t\taccessToken: 'test-access-token',\n\t\t\t\trefreshToken: 'test-refresh-token',\n\t\t\t\taccessTokenTTLMS: 3_600_000,\n\t\t\t\tacquiredAtMS: 1,\n\t\t\t};\n\t\t\tconst getTokensStub = sandbox.stub().resolves(tokenInfo);\n\t\t\tconst sdk = {\n\t\t\t\ttokenManager: {\n\t\t\t\t\tgetTokens: getTokensStub,\n\t\t\t\t},\n\t\t\t};\n\n\t\t\tconst result = await getTokenInfoByAuthCode(\n\t\t\t\tsdk,\n\t\t\t\t'auth-code',\n\t\t\t\t'http://localhost:3000/callback'\n\t\t\t);\n\n\t\t\tassert.strictEqual(result, tokenInfo);\n\t\t\tassert.isTrue(getTokensStub.calledOnce);\n\t\t\tassert.deepEqual(getTokensStub.firstCall.args[0], {\n\t\t\t\tgrant_type: 'authorization_code',\n\t\t\t\tcode: 'auth-code',\n\t\t\t\tredirect_uri: 'http://localhost:3000/callback',\n\t\t\t});\n\t\t\tassert.isNull(getTokensStub.firstCall.args[1]);\n\t\t});\n\n\t\tit('should throw when token manager is unavailable', async function () {\n\t\t\ttry {\n\t\t\t\tawait getTokenInfoByAuthCode(\n\t\t\t\t\t{},\n\t\t\t\t\t'auth-code',\n\t\t\t\t\t'http://localhost:3000/callback',\n\t\t\t\t\t'pkce-verifier'\n\t\t\t\t);\n\t\t\t\tassert.fail('Expected getTokenInfoByAuthCode to throw');\n\t\t\t} catch (error) {\n\t\t\t\tassert.include(\n\t\t\t\t\terror.message,\n\t\t\t\t\t'OAuth token manager is unavailable'\n\t\t\t\t);\n\t\t\t}\n\t\t});\n\t});\n\n\tdescribe('assertValidOAuthCode', function () {\n\t\tit('should throw when code is undefined, null, or empty', function () {\n\t\t\tfor (const invalidCode of [undefined, null, '']) {\n\t\t\t\tassert.throws(() => {\n\t\t\t\t\tassertValidOAuthCode(invalidCode);\n\t\t\t\t}, /Invalid OAuth code received in callback/u);\n\t\t\t}\n\t\t});\n\n\t\tit('should not throw for a non-empty string code', function () {\n\t\t\tassert.doesNotThrow(() => {\n\t\t\t\tassertValidOAuthCode('valid-code');\n\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('login command flags', function () {\n\t\tit('should expose --default-box-app flag', function () {\n\t\t\tassert.property(OAuthLoginCommand.flags, 'default-box-app');\n\t\t});\n\n\t\tit('should expose --platform-app flag', function () {\n\t\t\tassert.property(OAuthLoginCommand.flags, 'platform-app');\n\t\t});\n\n\t\tit('should mark --platform-app and --default-box-app as mutually exclusive', function () {\n\t\t\tassert.deepInclude(OAuthLoginCommand.flags['platform-app'], {\n\t\t\t\texclusive: ['default-box-app'],\n\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('promptForAuthMethod', function () {\n\t\tit('should use default box app when user enters \"1\"', async function () {\n\t\t\tconst promptStub = sandbox\n\t\t\t\t.stub()\n\t\t\t\t.onFirstCall()\n\t\t\t\t.resolves({ choice: '1' });\n\n\t\t\tconst result = await OAuthLoginCommand._test.promptForAuthMethod({\n\t\t\t\tprompt: promptStub,\n\t\t\t});\n\n\t\t\tassert.isTrue(promptStub.calledOnce);\n\t\t\tassert.deepEqual(result, {\n\t\t\t\tuseDefaultBoxApp: true,\n\t\t\t\tclientId: DEFAULT_CLIENT_ID,\n\t\t\t\tclientSecret: DEFAULT_CLIENT_SECRET,\n\t\t\t});\n\t\t});\n\n\t\tit('should prompt for client ID and secret when user enters \"2\"', async function () {\n\t\t\tconst promptStub = sandbox\n\t\t\t\t.stub()\n\t\t\t\t.onFirstCall()\n\t\t\t\t.resolves({ choice: '2' })\n\t\t\t\t.onSecondCall()\n\t\t\t\t.resolves({ clientId: 'custom-client-id' })\n\t\t\t\t.onThirdCall()\n\t\t\t\t.resolves({ clientSecret: 'custom-client-secret' });\n\n\t\t\tconst result = await OAuthLoginCommand._test.promptForAuthMethod({\n\t\t\t\tprompt: promptStub,\n\t\t\t});\n\n\t\t\tassert.strictEqual(promptStub.callCount, 3);\n\t\t\tassert.deepEqual(result, {\n\t\t\t\tuseDefaultBoxApp: false,\n\t\t\t\tclientId: 'custom-client-id',\n\t\t\t\tclientSecret: 'custom-client-secret',\n\t\t\t});\n\t\t});\n\n\t\tit('should treat input between 16 and 99 characters as client ID and prompt for secret', async function () {\n\t\t\tconst clientId32 = 'abcdefghijklmnopqrstuvwxyz123456';\n\t\t\tconst promptStub = sandbox\n\t\t\t\t.stub()\n\t\t\t\t.onFirstCall()\n\t\t\t\t.resolves({ choice: clientId32 })\n\t\t\t\t.onSecondCall()\n\t\t\t\t.resolves({ clientSecret: 'my-secret' });\n\n\t\t\tconst result = await OAuthLoginCommand._test.promptForAuthMethod({\n\t\t\t\tprompt: promptStub,\n\t\t\t});\n\n\t\t\tassert.strictEqual(promptStub.callCount, 2);\n\t\t\tassert.deepEqual(result, {\n\t\t\t\tuseDefaultBoxApp: false,\n\t\t\t\tclientId: clientId32,\n\t\t\t\tclientSecret: 'my-secret',\n\t\t\t});\n\t\t});\n\n\t\tit('should treat input with surrounding whitespace as client ID when trimmed length is valid', async function () {\n\t\t\tconst clientId32 = 'abcdefghijklmnopqrstuvwxyz123456';\n\t\t\tconst promptStub = sandbox\n\t\t\t\t.stub()\n\t\t\t\t.onFirstCall()\n\t\t\t\t.resolves({ choice: `  ${clientId32}  ` })\n\t\t\t\t.onSecondCall()\n\t\t\t\t.resolves({ clientSecret: 'my-secret' });\n\n\t\t\tconst result = await OAuthLoginCommand._test.promptForAuthMethod({\n\t\t\t\tprompt: promptStub,\n\t\t\t});\n\n\t\t\tassert.strictEqual(promptStub.callCount, 2);\n\t\t\tassert.deepEqual(result, {\n\t\t\t\tuseDefaultBoxApp: false,\n\t\t\t\tclientId: clientId32,\n\t\t\t\tclientSecret: 'my-secret',\n\t\t\t});\n\t\t});\n\n\t\tit('should repeat prompt on invalid input then accept valid choice', async function () {\n\t\t\tconst promptStub = sandbox\n\t\t\t\t.stub()\n\t\t\t\t.onFirstCall()\n\t\t\t\t.resolves({ choice: 'invalid' })\n\t\t\t\t.onSecondCall()\n\t\t\t\t.resolves({ choice: '' })\n\t\t\t\t.onCall(2)\n\t\t\t\t.resolves({ choice: '1' });\n\n\t\t\tconst result = await OAuthLoginCommand._test.promptForAuthMethod({\n\t\t\t\tprompt: promptStub,\n\t\t\t});\n\n\t\t\tassert.strictEqual(promptStub.callCount, 3);\n\t\t\tassert.deepEqual(result, {\n\t\t\t\tuseDefaultBoxApp: true,\n\t\t\t\tclientId: DEFAULT_CLIENT_ID,\n\t\t\t\tclientSecret: DEFAULT_CLIENT_SECRET,\n\t\t\t});\n\t\t});\n\n\t\tit('should verify prompt message contains expected text', async function () {\n\t\t\tconst promptStub = sandbox\n\t\t\t\t.stub()\n\t\t\t\t.onFirstCall()\n\t\t\t\t.resolves({ choice: '1' });\n\n\t\t\tawait OAuthLoginCommand._test.promptForAuthMethod({\n\t\t\t\tprompt: promptStub,\n\t\t\t});\n\n\t\t\tconst promptConfig = promptStub.firstCall.args[0][0];\n\t\t\tassert.include(\n\t\t\t\tpromptConfig.message,\n\t\t\t\t'How would you like to authenticate?'\n\t\t\t);\n\t\t\tassert.include(\n\t\t\t\tpromptConfig.message,\n\t\t\t\t'[1] Log-in as a Box user (OAuth)'\n\t\t\t);\n\t\t\tassert.include(promptConfig.message, '[2] Use a Box Platform App');\n\t\t\tassert.include(promptConfig.message, '[q] Quit');\n\t\t\tassert.include(promptConfig.message, 'Enter 1, 2, or q:');\n\t\t});\n\n\t\tit('should return null when user enters q to quit', async function () {\n\t\t\tconst promptStub = sandbox\n\t\t\t\t.stub()\n\t\t\t\t.onFirstCall()\n\t\t\t\t.resolves({ choice: 'q' });\n\n\t\t\tconst result = await OAuthLoginCommand._test.promptForAuthMethod({\n\t\t\t\tprompt: promptStub,\n\t\t\t});\n\n\t\t\tassert.strictEqual(result, null);\n\t\t});\n\n\t\tit('should return null when user enters Q to quit', async function () {\n\t\t\tconst promptStub = sandbox\n\t\t\t\t.stub()\n\t\t\t\t.onFirstCall()\n\t\t\t\t.resolves({ choice: 'Q' });\n\n\t\t\tconst result = await OAuthLoginCommand._test.promptForAuthMethod({\n\t\t\t\tprompt: promptStub,\n\t\t\t});\n\n\t\t\tassert.strictEqual(result, null);\n\t\t});\n\n\t\tit('should use correct messages when prompting for Client ID and Secret', async function () {\n\t\t\tconst promptStub = sandbox\n\t\t\t\t.stub()\n\t\t\t\t.onFirstCall()\n\t\t\t\t.resolves({ choice: '2' })\n\t\t\t\t.onSecondCall()\n\t\t\t\t.resolves({ clientId: 'test-id' })\n\t\t\t\t.onThirdCall()\n\t\t\t\t.resolves({ clientSecret: 'test-secret' });\n\n\t\t\tawait OAuthLoginCommand._test.promptForAuthMethod({\n\t\t\t\tprompt: promptStub,\n\t\t\t});\n\n\t\t\tconst clientIdPromptConfig = promptStub.secondCall.args[0][0];\n\t\t\tassert.strictEqual(\n\t\t\t\tclientIdPromptConfig.message,\n\t\t\t\t'Enter the Client ID:'\n\t\t\t);\n\n\t\t\tconst clientSecretPromptConfig = promptStub.thirdCall.args[0][0];\n\t\t\tassert.strictEqual(\n\t\t\t\tclientSecretPromptConfig.message,\n\t\t\t\t'Enter the Client Secret:'\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe('promptForCustomAppCredentials', function () {\n\t\tit('should prompt for both client ID and secret when no client ID is given', async function () {\n\t\t\tconst promptStub = sandbox\n\t\t\t\t.stub()\n\t\t\t\t.onFirstCall()\n\t\t\t\t.resolves({ clientId: ' my-client-id ' })\n\t\t\t\t.onSecondCall()\n\t\t\t\t.resolves({ clientSecret: 'my-secret' });\n\n\t\t\tconst result =\n\t\t\t\tawait OAuthLoginCommand._test.promptForPlatformAppCredentials({\n\t\t\t\t\tprompt: promptStub,\n\t\t\t\t});\n\n\t\t\tassert.strictEqual(promptStub.callCount, 2);\n\t\t\tassert.deepEqual(result, {\n\t\t\t\tuseDefaultBoxApp: false,\n\t\t\t\tclientId: 'my-client-id',\n\t\t\t\tclientSecret: 'my-secret',\n\t\t\t});\n\t\t});\n\n\t\tit('should only prompt for secret when client ID is provided', async function () {\n\t\t\tconst promptStub = sandbox\n\t\t\t\t.stub()\n\t\t\t\t.onFirstCall()\n\t\t\t\t.resolves({ clientSecret: 'my-secret' });\n\n\t\t\tconst result =\n\t\t\t\tawait OAuthLoginCommand._test.promptForPlatformAppCredentials(\n\t\t\t\t\t{ prompt: promptStub },\n\t\t\t\t\t'pre-filled-client-id'\n\t\t\t\t);\n\n\t\t\tassert.isTrue(promptStub.calledOnce);\n\t\t\tassert.deepEqual(result, {\n\t\t\t\tuseDefaultBoxApp: false,\n\t\t\t\tclientId: 'pre-filled-client-id',\n\t\t\t\tclientSecret: 'my-secret',\n\t\t\t});\n\t\t});\n\n\t\tit('should use correct prompt messages', async function () {\n\t\t\tconst promptStub = sandbox\n\t\t\t\t.stub()\n\t\t\t\t.onFirstCall()\n\t\t\t\t.resolves({ clientId: 'cid' })\n\t\t\t\t.onSecondCall()\n\t\t\t\t.resolves({ clientSecret: 'cs' });\n\n\t\t\tawait OAuthLoginCommand._test.promptForPlatformAppCredentials({\n\t\t\t\tprompt: promptStub,\n\t\t\t});\n\n\t\t\tassert.strictEqual(\n\t\t\t\tpromptStub.firstCall.args[0][0].message,\n\t\t\t\t'Enter the Client ID:'\n\t\t\t);\n\t\t\tassert.strictEqual(\n\t\t\t\tpromptStub.secondCall.args[0][0].message,\n\t\t\t\t'Enter the Client Secret:'\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe('reauthorize with non-existent environment', function () {\n\t\tlet getEnvironmentsStub;\n\n\t\tbeforeEach(function () {\n\t\t\tgetEnvironmentsStub = sandbox.stub(\n\t\t\t\tBoxCommand.prototype,\n\t\t\t\t'getEnvironments'\n\t\t\t);\n\t\t});\n\n\t\tit('should show error when specified env does not exist and no current env', async function () {\n\t\t\tgetEnvironmentsStub.resolves({ default: '', environments: {} });\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command(['login', '--reauthorize', '-n', 'nonexistent'])\n\t\t\t\t.it(\n\t\t\t\t\t'shows error when env does not exist and no current env',\n\t\t\t\t\t(ctx) => {\n\t\t\t\t\t\tassert.include(\n\t\t\t\t\t\t\tctx.stdout,\n\t\t\t\t\t\t\t'The \"nonexistent\" environment does not exist'\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t});\n\n\t\tit('should show error when specified env does not exist and current env is not OAuth', async function () {\n\t\t\tgetEnvironmentsStub.resolves({\n\t\t\t\tdefault: 'jwt-env',\n\t\t\t\tenvironments: {\n\t\t\t\t\t'jwt-env': { authMethod: 'jwt', clientId: 'cid' },\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command(['login', '--reauthorize', '-n', 'nonexistent'])\n\t\t\t\t.it(\n\t\t\t\t\t'shows error when env does not exist and current is not oauth',\n\t\t\t\t\t(ctx) => {\n\t\t\t\t\t\tassert.include(\n\t\t\t\t\t\t\tctx.stdout,\n\t\t\t\t\t\t\t'The \"nonexistent\" environment does not exist'\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t});\n\n\t\tit('should show error when specified env does not exist and name is not oauth (even if current is OAuth)', async function () {\n\t\t\tgetEnvironmentsStub.resolves({\n\t\t\t\tdefault: 'my-oauth',\n\t\t\t\tenvironments: {\n\t\t\t\t\t'my-oauth': {\n\t\t\t\t\t\tauthMethod: 'oauth20',\n\t\t\t\t\t\tclientId: DEFAULT_CLIENT_ID,\n\t\t\t\t\t\tclientSecret: DEFAULT_CLIENT_SECRET,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command(['login', '--reauthorize', '-n', 'nonexistent'])\n\t\t\t\t.it('does not fallback when name is not oauth', (ctx) => {\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\tctx.stdout,\n\t\t\t\t\t\t'The \"nonexistent\" environment does not exist'\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t});\n\n\t\tit('should use current OAuth env when name is oauth and that env does not exist', async function () {\n\t\t\tconst promptStub = sandbox.stub(inquirer, 'prompt').resolves({\n\t\t\t\tcode: 'test-code',\n\t\t\t\tstate: 'test-state',\n\t\t\t});\n\t\t\tgetEnvironmentsStub.resolves({\n\t\t\t\tdefault: 'my-oauth',\n\t\t\t\tenvironments: {\n\t\t\t\t\t'my-oauth': {\n\t\t\t\t\t\tauthMethod: 'oauth20',\n\t\t\t\t\t\tclientId: DEFAULT_CLIENT_ID,\n\t\t\t\t\t\tclientSecret: DEFAULT_CLIENT_SECRET,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\t'login',\n\t\t\t\t\t'--reauthorize',\n\t\t\t\t\t'-n',\n\t\t\t\t\t'oauth',\n\t\t\t\t\t'--default-box-app',\n\t\t\t\t\t'--code',\n\t\t\t\t\t'--port',\n\t\t\t\t\t'16987',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'falls back to current oauth env when name is oauth and env does not exist',\n\t\t\t\t\t(ctx) => {\n\t\t\t\t\t\tassert.notInclude(\n\t\t\t\t\t\t\tctx.stdout,\n\t\t\t\t\t\t\t'The \"oauth\" environment does not exist'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.include(ctx.stdout, 'Please open');\n\t\t\t\t\t\tassert.isTrue(promptStub.calledOnce);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t});\n\t});\n\n\tdescribe('oauth callback command behavior', function () {\n\t\tlet unsolicitedStatusPromise;\n\t\ttest.do(() => {\n\t\t\tOAuthLoginCommand._test.setOpenAuthorizeInBrowser(() => {});\n\t\t\tOAuthLoginCommand._test.setOAuthCallbackTimeoutMs(50);\n\t\t\tunsolicitedStatusPromise = (async () => {\n\t\t\t\tawait waitForLoopbackPort(Number.parseInt('19093', 10));\n\t\t\t\treturn sendCallback(\n\t\t\t\t\t'http://localhost:19093/callback?state=wrong-state&code=unsolicited'\n\t\t\t\t);\n\t\t\t})();\n\t\t})\n\t\t\t.stub(BoxCommand.prototype, '_loadSettings', (stub) => stub.resolves({}))\n\t\t\t.stub(BoxCommand.prototype, 'getEnvironments', (stub) =>\n\t\t\t\tstub.resolves({ default: '', environments: {} })\n\t\t\t)\n\t\t\t.stub(inquirer, 'prompt', (stub) =>\n\t\t\t\tstub\n\t\t\t\t\t.onFirstCall()\n\t\t\t\t\t.resolves({ clientId: 'cid' })\n\t\t\t\t\t.onSecondCall()\n\t\t\t\t\t.resolves({ clientSecret: 'secret' })\n\t\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['login', '--platform-app', '--port', '19093'])\n\t\t\t.it(\n\t\t\t\t'should fail login when callback state is invalid',\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\tconst statusCode = await unsolicitedStatusPromise;\n\t\t\t\t\tassert.strictEqual(statusCode, 500);\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\tctx.stderr,\n\t\t\t\t\t\t'Login failed: Invalid OAuth state received in callback'\n\t\t\t\t\t);\n\t\t\t\t\tassert.notInclude(\n\t\t\t\t\t\tctx.stderr,\n\t\t\t\t\t\t'Login timed out waiting for OAuth callback'\n\t\t\t\t\t);\n\t\t\t\t\tOAuthLoginCommand._test.resetOpenAuthorizeInBrowser();\n\t\t\t\t\tOAuthLoginCommand._test.resetOAuthCallbackTimeoutMs();\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.do(() => {\n\t\t\tOAuthLoginCommand._test.setOpenAuthorizeInBrowser(() => {});\n\t\t\tOAuthLoginCommand._test.setOAuthCallbackTimeoutMs(50);\n\t\t})\n\t\t\t.stub(BoxCommand.prototype, '_loadSettings', (stub) => stub.resolves({}))\n\t\t\t.stub(BoxCommand.prototype, 'getEnvironments', (stub) =>\n\t\t\t\tstub.resolves({ default: '', environments: {} })\n\t\t\t)\n\t\t\t.stub(inquirer, 'prompt', (stub) =>\n\t\t\t\tstub\n\t\t\t\t\t.onFirstCall()\n\t\t\t\t\t.resolves({ clientId: 'cid' })\n\t\t\t\t\t.onSecondCall()\n\t\t\t\t\t.resolves({ clientSecret: 'secret' })\n\t\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['login', '--platform-app', '--port', '19094'])\n\t\t\t.it('should time out when no callback is received', (ctx) => {\n\t\t\t\tassert.include(\n\t\t\t\t\tctx.stderr,\n\t\t\t\t\t'Login timed out waiting for OAuth callback'\n\t\t\t\t);\n\t\t\t\tOAuthLoginCommand._test.resetOpenAuthorizeInBrowser();\n\t\t\t\tOAuthLoginCommand._test.resetOAuthCallbackTimeoutMs();\n\t\t\t});\n\n\t\tlet busyServer;\n\t\t// Use a high random port to reduce clashes with common local services.\n\t\tconst busyPort = 30000 + Math.floor(Math.random() * 10000);\n\t\ttest.do(async () => {\n\t\t\tOAuthLoginCommand._test.setOpenAuthorizeInBrowser(() => {});\n\t\t\tOAuthLoginCommand._test.setOAuthCallbackTimeoutMs(50);\n\t\t\tbusyServer = nodeHttp.createServer();\n\t\t\tawait new Promise((resolve, reject) => {\n\t\t\t\tbusyServer.once('error', reject);\n\t\t\t\tbusyServer.listen(busyPort, 'localhost', resolve);\n\t\t\t});\n\t\t})\n\t\t\t.stub(BoxCommand.prototype, '_loadSettings', (stub) => stub.resolves({}))\n\t\t\t.stub(BoxCommand.prototype, 'getEnvironments', (stub) =>\n\t\t\t\tstub.resolves({ default: '', environments: {} })\n\t\t\t)\n\t\t\t.stub(inquirer, 'prompt', (stub) =>\n\t\t\t\tstub\n\t\t\t\t\t.onFirstCall()\n\t\t\t\t\t.resolves({ clientId: 'cid' })\n\t\t\t\t\t.onSecondCall()\n\t\t\t\t\t.resolves({ clientSecret: 'secret' })\n\t\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['login', '--platform-app', '--port', String(busyPort)])\n\t\t\t.it(\n\t\t\t\t'should fail with a friendly message when callback port is in use',\n\t\t\t\tasync (ctx) => {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tassert.include(\n\t\t\t\t\t\t\tctx.stderr,\n\t\t\t\t\t\t\t`Port ${busyPort} is already in use. Please close the application using this port or use --port to specify a different port.`\n\t\t\t\t\t\t);\n\t\t\t\t\t} finally {\n\t\t\t\t\t\tOAuthLoginCommand._test.resetOpenAuthorizeInBrowser();\n\t\t\t\t\t\tOAuthLoginCommand._test.resetOAuthCallbackTimeoutMs();\n\t\t\t\t\t\tif (busyServer) {\n\t\t\t\t\t\t\tawait new Promise((resolve) => busyServer.close(resolve));\n\t\t\t\t\t\t\tbusyServer = null;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/logout.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst { assert } = require('chai');\nconst sinon = require('sinon');\nconst mockery = require('mockery');\nconst BoxCommand = require('../../src/box-command');\nconst CLITokenCache = require('../../src/token-cache');\nconst inquirer = require('inquirer');\n\nconst OAUTH_ENV = {\n\tdefault: 'oauth',\n\tenvironments: {\n\t\toauth: {\n\t\t\tauthMethod: 'oauth20',\n\t\t\tclientId: 'cid',\n\t\t\tclientSecret: 'secret',\n\t\t},\n\t},\n};\n\nconst OAUTH_ENV_NO_CREDS = {\n\tdefault: 'oauth',\n\tenvironments: {\n\t\toauth: {\n\t\t\tauthMethod: 'oauth20',\n\t\t\tclientId: '',\n\t\t\tclientSecret: '',\n\t\t},\n\t},\n};\n\ndescribe('Logout', function () {\n\tlet sandbox;\n\tlet getEnvironmentsStub;\n\tlet tokenCacheGetStub;\n\tlet tokenCacheClearStub;\n\tlet revokeTokensStub;\n\tlet OAuthLogoutCommand;\n\n\tbeforeEach(function () {\n\t\tsandbox = sinon.createSandbox();\n\n\t\tgetEnvironmentsStub = sandbox.stub(\n\t\t\tBoxCommand.prototype,\n\t\t\t'getEnvironments'\n\t\t);\n\t\ttokenCacheGetStub = sandbox.stub(CLITokenCache.prototype, 'get');\n\t\ttokenCacheClearStub = sandbox.stub(CLITokenCache.prototype, 'clear');\n\n\t\tgetEnvironmentsStub.resolves(OAUTH_ENV);\n\n\t\trevokeTokensStub = sandbox.stub();\n\t\tmockery.enable({ useCleanCache: true, warnOnUnregistered: false });\n\t\tmockery.registerMock('box-node-sdk', {\n\t\t\tdefault: function () {\n\t\t\t\treturn { revokeTokens: revokeTokensStub };\n\t\t\t},\n\t\t});\n\t\tmockery.registerAllowable('../../src/commands/logout', true);\n\t\tdelete require.cache[require.resolve('../../src/commands/logout')];\n\t\tOAuthLogoutCommand = require('../../src/commands/logout');\n\t});\n\n\tafterEach(function () {\n\t\tsandbox.restore();\n\t\tmockery.deregisterAll();\n\t\tmockery.disable();\n\t});\n\n\tdescribe('logout command', function () {\n\t\tit('should expose --force flag', function () {\n\t\t\tassert.property(OAuthLogoutCommand.flags, 'force');\n\t\t\tassert.strictEqual(OAuthLogoutCommand.flags.force.char, 'f');\n\t\t\tassert.include(\n\t\t\t\tOAuthLogoutCommand.flags.force.description,\n\t\t\t\t'Skip confirmation prompt'\n\t\t\t);\n\t\t});\n\n\t\tit('should expose --on-revoke-failure flag', function () {\n\t\t\tassert.property(OAuthLogoutCommand.flags, 'on-revoke-failure');\n\t\t\tassert.include(\n\t\t\t\tOAuthLogoutCommand.flags['on-revoke-failure'].description,\n\t\t\t\t'clear'\n\t\t\t);\n\t\t\tassert.include(\n\t\t\t\tOAuthLogoutCommand.flags['on-revoke-failure'].description,\n\t\t\t\t'abort'\n\t\t\t);\n\t\t\tassert.sameMembers(\n\t\t\t\tOAuthLogoutCommand.flags['on-revoke-failure'].options,\n\t\t\t\t['clear', 'abort']\n\t\t\t);\n\t\t});\n\n\t\tit('should show error when no current environment', async function () {\n\t\t\tgetEnvironmentsStub.resolves({ default: null, environments: {} });\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.command(['logout', '--force'])\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\terror.message,\n\t\t\t\t\t\t'No current environment found'\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t\t.it('errors when no current environment');\n\t\t});\n\n\t\tit('should show already logged out when no access token', async function () {\n\t\t\ttokenCacheGetStub.resolves();\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stub(CLITokenCache.prototype, 'get', tokenCacheGetStub)\n\t\t\t\t.stdout()\n\t\t\t\t.command(['logout', '--force'])\n\t\t\t\t.it('shows already logged out', (ctx) => {\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\tctx.stdout,\n\t\t\t\t\t\t'You are already logged out from \"oauth\" environment'\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t});\n\n\t\tit('should cancel when user declines confirmation (no --force)', async function () {\n\t\t\ttokenCacheGetStub.resolves({\n\t\t\t\taccessToken: 'test-token',\n\t\t\t\trefreshToken: 'refresh',\n\t\t\t});\n\t\t\tconst confirmStub = sandbox\n\t\t\t\t.stub(BoxCommand.prototype, 'confirm')\n\t\t\t\t.resolves(false);\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stub(BoxCommand.prototype, 'confirm', confirmStub)\n\t\t\t\t.stub(CLITokenCache.prototype, 'get', tokenCacheGetStub)\n\t\t\t\t.stdout()\n\t\t\t\t.command(['logout'])\n\t\t\t\t.it('cancels when user declines', (ctx) => {\n\t\t\t\t\tassert.include(ctx.stdout, 'Logout cancelled');\n\t\t\t\t\tassert.isTrue(\n\t\t\t\t\t\tconfirmStub.calledWith(\n\t\t\t\t\t\t\tsinon.match(/logout from \"oauth\"/)\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t});\n\n\t\tit('should successfully logout when user confirms (no --force)', async function () {\n\t\t\ttokenCacheGetStub.resolves({\n\t\t\t\taccessToken: 'test-token',\n\t\t\t\trefreshToken: 'refresh',\n\t\t\t});\n\t\t\ttokenCacheClearStub.callsFake((cb) => cb(null));\n\t\t\tconst confirmStub = sandbox\n\t\t\t\t.stub(BoxCommand.prototype, 'confirm')\n\t\t\t\t.resolves(true);\n\t\t\trevokeTokensStub.resolves({ statusCode: 200 });\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stub(BoxCommand.prototype, 'confirm', confirmStub)\n\t\t\t\t.stub(CLITokenCache.prototype, 'get', tokenCacheGetStub)\n\t\t\t\t.stub(CLITokenCache.prototype, 'clear', tokenCacheClearStub)\n\t\t\t\t.stdout()\n\t\t\t\t.command(['logout'])\n\t\t\t\t.it('logs out when user confirms', (ctx) => {\n\t\t\t\t\tassert.isTrue(\n\t\t\t\t\t\tconfirmStub.calledWith(\n\t\t\t\t\t\t\tsinon.match(/logout from \"oauth\"/)\n\t\t\t\t\t\t)\n\t\t\t\t\t);\n\t\t\t\t\tassert.isTrue(revokeTokensStub.calledWith('test-token'));\n\t\t\t\t\tassert.isTrue(tokenCacheClearStub.called);\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\tctx.stdout,\n\t\t\t\t\t\t'Successfully logged out from \"oauth\"'\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t});\n\n\t\tit('should skip revoke and clear cache when revoke returns 400 invalid_token', async function () {\n\t\t\ttokenCacheGetStub.resolves({\n\t\t\t\taccessToken: 'test-token',\n\t\t\t\trefreshToken: 'refresh',\n\t\t\t});\n\t\t\ttokenCacheClearStub.callsFake((cb) => cb(null));\n\n\t\t\trevokeTokensStub.resolves({\n\t\t\t\tstatusCode: 400,\n\t\t\t\tbody: { error: 'invalid_token' },\n\t\t\t});\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stub(CLITokenCache.prototype, 'get', tokenCacheGetStub)\n\t\t\t\t.stub(CLITokenCache.prototype, 'clear', tokenCacheClearStub)\n\t\t\t\t.stdout()\n\t\t\t\t.command(['logout', '--force'])\n\t\t\t\t.it(\n\t\t\t\t\t'skips revoke and clears cache for invalid_token',\n\t\t\t\t\t(ctx) => {\n\t\t\t\t\t\tassert.isTrue(\n\t\t\t\t\t\t\trevokeTokensStub.calledWith('test-token')\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.isTrue(tokenCacheClearStub.called);\n\t\t\t\t\t\tassert.include(\n\t\t\t\t\t\t\tctx.stdout,\n\t\t\t\t\t\t\t'Access token is already invalid'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.include(ctx.stdout, 'Successfully logged out');\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t});\n\n\t\tit('should clear cache when revoke returns other 400 and user selects clear', async function () {\n\t\t\ttokenCacheGetStub.resolves({\n\t\t\t\taccessToken: 'test-token',\n\t\t\t\trefreshToken: 'refresh',\n\t\t\t});\n\t\t\ttokenCacheClearStub.callsFake((cb) => cb(null));\n\n\t\t\trevokeTokensStub.resolves({\n\t\t\t\tstatusCode: 400,\n\t\t\t\tbody: { error: 'invalid_request' },\n\t\t\t});\n\n\t\t\tconst inquirerPromptStub = sandbox\n\t\t\t\t.stub(inquirer, 'prompt')\n\t\t\t\t.resolves({\n\t\t\t\t\taction: 'clear',\n\t\t\t\t});\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stub(CLITokenCache.prototype, 'get', tokenCacheGetStub)\n\t\t\t\t.stub(CLITokenCache.prototype, 'clear', tokenCacheClearStub)\n\t\t\t\t.stub(inquirer, 'prompt', inquirerPromptStub)\n\t\t\t\t.stdout()\n\t\t\t\t.command(['logout', '--force'])\n\t\t\t\t.it('clears cache when user selects clear', (ctx) => {\n\t\t\t\t\tassert.isTrue(revokeTokensStub.calledWith('test-token'));\n\t\t\t\t\tassert.isTrue(tokenCacheClearStub.called);\n\t\t\t\t\tassert.include(ctx.stdout, 'Successfully logged out');\n\t\t\t\t});\n\t\t});\n\n\t\tit('should successfully logout and clear cache when revoke succeeds', async function () {\n\t\t\ttokenCacheGetStub.resolves({\n\t\t\t\taccessToken: 'test-token',\n\t\t\t\trefreshToken: 'refresh',\n\t\t\t});\n\t\t\ttokenCacheClearStub.callsFake((cb) => cb(null));\n\n\t\t\trevokeTokensStub.resolves({ statusCode: 200 });\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stub(CLITokenCache.prototype, 'get', tokenCacheGetStub)\n\t\t\t\t.stub(CLITokenCache.prototype, 'clear', tokenCacheClearStub)\n\t\t\t\t.stdout()\n\t\t\t\t.command(['logout', '--force'])\n\t\t\t\t.it('successfully logs out when revoke succeeds', (ctx) => {\n\t\t\t\t\tassert.isTrue(revokeTokensStub.calledWith('test-token'));\n\t\t\t\t\tassert.isTrue(tokenCacheClearStub.called);\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\tctx.stdout,\n\t\t\t\t\t\t'Successfully logged out from \"oauth\"'\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t});\n\n\t\tit('should clear cache when revoke fails and user selects clear', async function () {\n\t\t\ttokenCacheGetStub.resolves({\n\t\t\t\taccessToken: 'test-token',\n\t\t\t\trefreshToken: 'refresh',\n\t\t\t});\n\t\t\ttokenCacheClearStub.callsFake((cb) => cb(null));\n\n\t\t\trevokeTokensStub.rejects(new Error('ECONNREFUSED'));\n\n\t\t\tconst inquirerPromptStub = sandbox\n\t\t\t\t.stub(inquirer, 'prompt')\n\t\t\t\t.resolves({\n\t\t\t\t\taction: 'clear',\n\t\t\t\t});\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stub(CLITokenCache.prototype, 'get', tokenCacheGetStub)\n\t\t\t\t.stub(CLITokenCache.prototype, 'clear', tokenCacheClearStub)\n\t\t\t\t.stub(inquirer, 'prompt', inquirerPromptStub)\n\t\t\t\t.stdout()\n\t\t\t\t.command(['logout', '--force'])\n\t\t\t\t.it(\n\t\t\t\t\t'clears cache when revoke fails and user selects clear',\n\t\t\t\t\t(ctx) => {\n\t\t\t\t\t\tassert.isTrue(tokenCacheClearStub.called);\n\t\t\t\t\t\tassert.include(ctx.stdout, 'Successfully logged out');\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t});\n\n\t\tit('should show abort message when revoke fails and user selects abort', async function () {\n\t\t\ttokenCacheGetStub.resolves({\n\t\t\t\taccessToken: 'test-token',\n\t\t\t\trefreshToken: 'refresh',\n\t\t\t});\n\n\t\t\trevokeTokensStub.rejects(new Error('ECONNREFUSED'));\n\n\t\t\tconst inquirerPromptStub = sandbox\n\t\t\t\t.stub(inquirer, 'prompt')\n\t\t\t\t.resolves({\n\t\t\t\t\taction: 'abort',\n\t\t\t\t});\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stub(CLITokenCache.prototype, 'get', tokenCacheGetStub)\n\t\t\t\t.stub(CLITokenCache.prototype, 'clear', tokenCacheClearStub)\n\t\t\t\t.stub(inquirer, 'prompt', inquirerPromptStub)\n\t\t\t\t.stdout()\n\t\t\t\t.command(['logout', '--force'])\n\t\t\t\t.it('shows abort message when user selects abort', (ctx) => {\n\t\t\t\t\tassert.isFalse(tokenCacheClearStub.called);\n\t\t\t\t\tassert.include(ctx.stdout, 'Logout aborted');\n\t\t\t\t\tassert.include(ctx.stdout, 'not revoked');\n\t\t\t\t\tassert.include(ctx.stdout, 'remains cached');\n\t\t\t\t});\n\t\t});\n\n\t\tit('should retry revoke when revoke fails and user selects retry, then succeed', async function () {\n\t\t\ttokenCacheGetStub.resolves({\n\t\t\t\taccessToken: 'test-token',\n\t\t\t\trefreshToken: 'refresh',\n\t\t\t});\n\t\t\ttokenCacheClearStub.callsFake((cb) => cb(null));\n\n\t\t\trevokeTokensStub\n\t\t\t\t.onFirstCall()\n\t\t\t\t.rejects(new Error('ECONNREFUSED'))\n\t\t\t\t.onSecondCall()\n\t\t\t\t.resolves({ statusCode: 200 });\n\n\t\t\tconst inquirerPromptStub = sandbox\n\t\t\t\t.stub(inquirer, 'prompt')\n\t\t\t\t.resolves({\n\t\t\t\t\taction: 'retry',\n\t\t\t\t});\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stub(CLITokenCache.prototype, 'get', tokenCacheGetStub)\n\t\t\t\t.stub(CLITokenCache.prototype, 'clear', tokenCacheClearStub)\n\t\t\t\t.stub(inquirer, 'prompt', inquirerPromptStub)\n\t\t\t\t.stdout()\n\t\t\t\t.command(['logout', '--force'])\n\t\t\t\t.it('retries revoke and succeeds', (ctx) => {\n\t\t\t\t\tassert.strictEqual(revokeTokensStub.callCount, 2);\n\t\t\t\t\tassert.isTrue(tokenCacheClearStub.called);\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\tctx.stdout,\n\t\t\t\t\t\t'Successfully logged out from \"oauth\"'\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t});\n\n\t\tit('should use --on-revoke-failure=clear when revoke fails (skips prompt)', async function () {\n\t\t\ttokenCacheGetStub.resolves({\n\t\t\t\taccessToken: 'test-token',\n\t\t\t\trefreshToken: 'refresh',\n\t\t\t});\n\t\t\ttokenCacheClearStub.callsFake((cb) => cb(null));\n\n\t\t\trevokeTokensStub.rejects(new Error('ECONNREFUSED'));\n\n\t\t\tconst inquirerPromptStub = sandbox.stub(inquirer, 'prompt');\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stub(CLITokenCache.prototype, 'get', tokenCacheGetStub)\n\t\t\t\t.stub(CLITokenCache.prototype, 'clear', tokenCacheClearStub)\n\t\t\t\t.stub(inquirer, 'prompt', inquirerPromptStub)\n\t\t\t\t.stdout()\n\t\t\t\t.command(['logout', '--force', '--on-revoke-failure=clear'])\n\t\t\t\t.it('clears cache using flag (no prompt)', (ctx) => {\n\t\t\t\t\tassert.isFalse(inquirerPromptStub.called);\n\t\t\t\t\tassert.isTrue(tokenCacheClearStub.called);\n\t\t\t\t\tassert.include(ctx.stdout, 'Successfully logged out');\n\t\t\t\t});\n\t\t});\n\n\t\tit('should use --on-revoke-failure=abort when revoke fails (skips prompt)', async function () {\n\t\t\ttokenCacheGetStub.resolves({\n\t\t\t\taccessToken: 'test-token',\n\t\t\t\trefreshToken: 'refresh',\n\t\t\t});\n\n\t\t\trevokeTokensStub.rejects(new Error('ECONNREFUSED'));\n\n\t\t\tconst inquirerPromptStub = sandbox.stub(inquirer, 'prompt');\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stub(CLITokenCache.prototype, 'get', tokenCacheGetStub)\n\t\t\t\t.stub(CLITokenCache.prototype, 'clear', tokenCacheClearStub)\n\t\t\t\t.stub(inquirer, 'prompt', inquirerPromptStub)\n\t\t\t\t.stdout()\n\t\t\t\t.command(['logout', '--force', '--on-revoke-failure=abort'])\n\t\t\t\t.it('aborts using flag (no prompt)', (ctx) => {\n\t\t\t\t\tassert.isFalse(inquirerPromptStub.called);\n\t\t\t\t\tassert.isFalse(tokenCacheClearStub.called);\n\t\t\t\t\tassert.include(ctx.stdout, 'Logout aborted');\n\t\t\t\t\tassert.include(ctx.stdout, 'remains cached');\n\t\t\t\t});\n\t\t});\n\n\t\tit('should clear cache when credentials invalid and user selects clear', async function () {\n\t\t\tgetEnvironmentsStub.resolves(OAUTH_ENV_NO_CREDS);\n\t\t\ttokenCacheGetStub.resolves({\n\t\t\t\taccessToken: 'test-token',\n\t\t\t\trefreshToken: 'refresh',\n\t\t\t});\n\t\t\ttokenCacheClearStub.callsFake((cb) => cb(null));\n\n\t\t\tconst inquirerPromptStub = sandbox\n\t\t\t\t.stub(inquirer, 'prompt')\n\t\t\t\t.resolves({\n\t\t\t\t\taction: 'clear',\n\t\t\t\t});\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stub(CLITokenCache.prototype, 'get', tokenCacheGetStub)\n\t\t\t\t.stub(CLITokenCache.prototype, 'clear', tokenCacheClearStub)\n\t\t\t\t.stub(inquirer, 'prompt', inquirerPromptStub)\n\t\t\t\t.stdout()\n\t\t\t\t.command(['logout', '--force'])\n\t\t\t\t.it(\n\t\t\t\t\t'clears cache when credentials invalid and user selects clear',\n\t\t\t\t\t(ctx) => {\n\t\t\t\t\t\tassert.isFalse(revokeTokensStub.called);\n\t\t\t\t\t\tassert.isTrue(tokenCacheClearStub.called);\n\t\t\t\t\t\tassert.include(ctx.stdout, 'Successfully logged out');\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t});\n\n\t\tit('should reject when tokenCache.clear fails', async function () {\n\t\t\ttokenCacheGetStub.resolves({\n\t\t\t\taccessToken: 'test-token',\n\t\t\t\trefreshToken: 'refresh',\n\t\t\t});\n\t\t\ttokenCacheClearStub.callsFake((cb) =>\n\t\t\t\tcb(new Error('Clear failed'))\n\t\t\t);\n\n\t\t\trevokeTokensStub.resolves({ statusCode: 200 });\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tBoxCommand.prototype,\n\t\t\t\t\t'getEnvironments',\n\t\t\t\t\tgetEnvironmentsStub\n\t\t\t\t)\n\t\t\t\t.stub(CLITokenCache.prototype, 'get', tokenCacheGetStub)\n\t\t\t\t.stub(CLITokenCache.prototype, 'clear', tokenCacheClearStub)\n\t\t\t\t.command(['logout', '--force'])\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tassert.include(error.message, 'Clear failed');\n\t\t\t\t})\n\t\t\t\t.it('rejects when tokenCache.clear fails');\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/commands/metadata-cascade-policies.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\n\ndescribe('Metadata Cascade Policies', function () {\n\tdescribe('metadata-cascade-policies:get', function () {\n\t\tlet cascadePolicyID = '84113349-794d-445c-b93c-d8481b223434',\n\t\t\tfixture = getFixture(\n\t\t\t\t'metadata-cascade-policies/get_metadata_cascade_policies_id_200'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/metadata_cascade_policies_get_yaml.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/metadata_cascade_policies/${cascadePolicyID}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-cascade-policies:get',\n\t\t\t\tcascadePolicyID,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get metadata cascade policy (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/metadata_cascade_policies/${cascadePolicyID}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-cascade-policies:get',\n\t\t\t\tcascadePolicyID,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get metadata cascade policy (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('metadata-cascade-policies:delete', function () {\n\t\tlet cascadePolicyID = '84113349-794d-445c-b93c-d8481b223434';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(`/2.0/metadata_cascade_policies/${cascadePolicyID}`)\n\t\t\t\t.reply(204)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'metadata-cascade-policies:delete',\n\t\t\t\tcascadePolicyID,\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should delete the cascade policy', (context) => {\n\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Successfully deleted policy ${cascadePolicyID}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tdescribe('metadata-cascade-policies', function () {\n\t\tlet folderID = '22222',\n\t\t\tenterpriseID = '11111',\n\t\t\tfixture = getFixture(\n\t\t\t\t'metadata-cascade-policies/get_metadata_cascade_policies_folder_id_200'\n\t\t\t),\n\t\t\tjsonOutput = getFixture(\n\t\t\t\t'output/metadata_cascade_policies_list_json.txt'\n\t\t\t),\n\t\t\ttableOutput = getFixture(\n\t\t\t\t'output/metadata_cascade_policies_list_table.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/metadata_cascade_policies')\n\t\t\t\t.query({ folder_id: folderID, limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-cascade-policies',\n\t\t\t\tfolderID,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should output cascade policies for folder (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/metadata_cascade_policies')\n\t\t\t\t.query({ folder_id: folderID, limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['metadata-cascade-policies', folderID, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should output cascade policies for folder (Table Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, tableOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/metadata_cascade_policies')\n\t\t\t\t.query({\n\t\t\t\t\tfolder_id: folderID,\n\t\t\t\t\towner_enterprise_id: enterpriseID,\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-cascade-policies',\n\t\t\t\tfolderID,\n\t\t\t\t`--owner-enterprise-id=${enterpriseID}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should output only cascade policies for enterprise when --owner-enterprise-id flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('metadata-cascade-policies:force-apply', function () {\n\t\tlet cascadePolicyID = '84113349-794d-445c-b93c-d8481b223434',\n\t\t\tresolution = 'overwrite';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(\n\t\t\t\t\t`/2.0/metadata_cascade_policies/${cascadePolicyID}/apply`,\n\t\t\t\t\t{\n\t\t\t\t\t\tconflict_resolution: resolution,\n\t\t\t\t\t}\n\t\t\t\t)\n\t\t\t\t.reply(202)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'metadata-cascade-policies:force-apply',\n\t\t\t\tcascadePolicyID,\n\t\t\t\t`--conflict-resolution=${resolution}`,\n\t\t\t\t'--no-color',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should force apply the cascade policy', (context) => {\n\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Successfully applied policy ${cascadePolicyID}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/commands/metadata-query.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\n\ndescribe('Metadata Query', function () {\n\tdescribe('metadata-query', function () {\n\t\tconst request = {\n\t\t\t\tfrom: 'enterprise_123456.contractTemplate',\n\t\t\t\tquery: 'amount >= :value',\n\t\t\t\tquery_params: {\n\t\t\t\t\tvalue: 100,\n\t\t\t\t},\n\t\t\t\tfields: [\n\t\t\t\t\t'created_at',\n\t\t\t\t\t'metadata.enterprise_123456.contractTemplate.amount',\n\t\t\t\t\t'metadata.enterprise_123456.contractTemplate.customerName',\n\t\t\t\t],\n\t\t\t\tancestor_folder_id: '5555',\n\t\t\t\torder_by: [\n\t\t\t\t\t{\n\t\t\t\t\t\tfield_key: 'amount',\n\t\t\t\t\t\tdirection: 'asc',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tlimit: 100,\n\t\t\t},\n\t\t\trequestWithMultipleValues = {\n\t\t\t\tfrom: 'enterprise_123456.contractTemplate',\n\t\t\t\tquery: 'name = :customerName',\n\t\t\t\tquery_params: {\n\t\t\t\t\tvalue: 100,\n\t\t\t\t\tvalue2: 'String',\n\t\t\t\t},\n\t\t\t\tfields: [\n\t\t\t\t\t'created_at',\n\t\t\t\t\t'metadata.enterprise_123456.contractTemplate.amount',\n\t\t\t\t\t'metadata.enterprise_123456.contractTemplate.customerName',\n\t\t\t\t],\n\t\t\t\tancestor_folder_id: '5555',\n\t\t\t\torder_by: [\n\t\t\t\t\t{\n\t\t\t\t\t\tfield_key: 'amount',\n\t\t\t\t\t\tdirection: 'asc',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tlimit: 100,\n\t\t\t},\n\t\t\trequestWithMultipleArrayValues = {\n\t\t\t\tfrom: 'enterprise_123456.contractTemplate',\n\t\t\t\tquery: 'name = :customerName',\n\t\t\t\tquery_params: {\n\t\t\t\t\tcustomerName: ['John Doe', 'Jane Doe'],\n\t\t\t\t},\n\t\t\t\tfields: [\n\t\t\t\t\t'created_at',\n\t\t\t\t\t'metadata.enterprise_123456.contractTemplate.amount',\n\t\t\t\t\t'metadata.enterprise_123456.contractTemplate.customerName',\n\t\t\t\t],\n\t\t\t\tancestor_folder_id: '5555',\n\t\t\t\torder_by: [\n\t\t\t\t\t{\n\t\t\t\t\t\tfield_key: 'amount',\n\t\t\t\t\t\tdirection: 'asc',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tlimit: 100,\n\t\t\t},\n\t\t\trequestWithMultipleArrayQueryParameters = {\n\t\t\t\tfrom: 'enterprise_123456.contractTemplate',\n\t\t\t\tquery: 'name = :customerName',\n\t\t\t\tquery_params: {\n\t\t\t\t\tcustomerName: ['John Doe', 'Jane Doe'],\n\t\t\t\t\tcustomerName2: ['Doe John', 'Doe Jane'],\n\t\t\t\t},\n\t\t\t\tfields: [\n\t\t\t\t\t'created_at',\n\t\t\t\t\t'metadata.enterprise_123456.contractTemplate.amount',\n\t\t\t\t\t'metadata.enterprise_123456.contractTemplate.customerName',\n\t\t\t\t],\n\t\t\t\tancestor_folder_id: '5555',\n\t\t\t\torder_by: [\n\t\t\t\t\t{\n\t\t\t\t\t\tfield_key: 'amount',\n\t\t\t\t\t\tdirection: 'asc',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tlimit: 100,\n\t\t\t},\n\t\t\tfixture = getFixture(\n\t\t\t\t'metadata-query/post_metadata_queries_execute_read'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/metadata_queries/execute_read', request)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-query',\n\t\t\t\trequest.from,\n\t\t\t\trequest.ancestor_folder_id,\n\t\t\t\t`--query=${request.query}`,\n\t\t\t\t`--query-params=value=${request.query_params.value}f`,\n\t\t\t\t`--extra-fields=${request.fields.join(',')}`,\n\t\t\t\t`--order-by=${request.order_by[0].field_key}=${request.order_by[0].direction}`,\n\t\t\t\t`--limit=${request.limit}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should query metadata', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(\n\t\t\t\t\t'/2.0/metadata_queries/execute_read',\n\t\t\t\t\trequestWithMultipleValues\n\t\t\t\t)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-query',\n\t\t\t\trequestWithMultipleValues.from,\n\t\t\t\trequestWithMultipleValues.ancestor_folder_id,\n\t\t\t\t`--query=${requestWithMultipleValues.query}`,\n\t\t\t\t`--query-param=value=${requestWithMultipleValues.query_params.value}f`,\n\t\t\t\t`--query-param=value2=${requestWithMultipleValues.query_params.value2}`,\n\t\t\t\t`--extra-fields=${requestWithMultipleValues.fields.join(',')}`,\n\t\t\t\t`--order-by=${requestWithMultipleValues.order_by[0].field_key}=${requestWithMultipleValues.order_by[0].direction}`,\n\t\t\t\t`--limit=${requestWithMultipleValues.limit}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should query metadata with multiple query-param',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(\n\t\t\t\t\t'/2.0/metadata_queries/execute_read',\n\t\t\t\t\trequestWithMultipleArrayValues\n\t\t\t\t)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-query',\n\t\t\t\trequestWithMultipleArrayValues.from,\n\t\t\t\trequestWithMultipleArrayValues.ancestor_folder_id,\n\t\t\t\t`--query=${requestWithMultipleArrayValues.query}`,\n\t\t\t\t`--query-param-array=customerName=${requestWithMultipleArrayValues.query_params.customerName.join(',')}`,\n\t\t\t\t`--extra-fields=${requestWithMultipleArrayValues.fields.join(',')}`,\n\t\t\t\t`--order-by=${requestWithMultipleArrayValues.order_by[0].field_key}=${requestWithMultipleArrayValues.order_by[0].direction}`,\n\t\t\t\t`--limit=${requestWithMultipleArrayValues.limit}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should query metadata with query-param', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(\n\t\t\t\t\t'/2.0/metadata_queries/execute_read',\n\t\t\t\t\trequestWithMultipleArrayQueryParameters\n\t\t\t\t)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-query',\n\t\t\t\trequestWithMultipleArrayQueryParameters.from,\n\t\t\t\trequestWithMultipleArrayQueryParameters.ancestor_folder_id,\n\t\t\t\t`--query=${requestWithMultipleArrayQueryParameters.query}`,\n\t\t\t\t`--query-param-array=customerName=${requestWithMultipleArrayQueryParameters.query_params.customerName.join(',')}`,\n\t\t\t\t`--query-param-array=customerName2=${requestWithMultipleArrayQueryParameters.query_params.customerName2.join(',')}`,\n\t\t\t\t`--extra-fields=${requestWithMultipleArrayQueryParameters.fields.join(',')}`,\n\t\t\t\t`--order-by=${requestWithMultipleArrayQueryParameters.order_by[0].field_key}=${requestWithMultipleArrayQueryParameters.order_by[0].direction}`,\n\t\t\t\t`--limit=${requestWithMultipleArrayQueryParameters.limit}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should query metadata with multiple query-params-array',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/metadata-templates.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\nconst leche = require('leche');\n\ndescribe('Metadata Templates', function () {\n\tdescribe('metadata-templates:cascade', function () {\n\t\tlet folderID = '22222',\n\t\t\tscope = 'enterprise',\n\t\t\ttemplateKey = 'testTemplate',\n\t\t\tfixture = getFixture(\n\t\t\t\t'metadata-cascade-policies/post_metadata_cascade_policies_201'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/metadata_cascade_policies_create_yaml.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/metadata_cascade_policies', {\n\t\t\t\t\tscope,\n\t\t\t\t\ttemplateKey,\n\t\t\t\t\tfolder_id: folderID,\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-templates:cascade',\n\t\t\t\ttemplateKey,\n\t\t\t\t`--folder=${folderID}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should create cascade policy (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/metadata_cascade_policies', {\n\t\t\t\t\tscope,\n\t\t\t\t\ttemplateKey,\n\t\t\t\t\tfolder_id: folderID,\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-templates:cascade',\n\t\t\t\ttemplateKey,\n\t\t\t\t`--folder=${folderID}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should create cascade policy (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/metadata_cascade_policies', {\n\t\t\t\t\tscope,\n\t\t\t\t\ttemplateKey,\n\t\t\t\t\tfolder_id: folderID,\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-cascade-policies:create',\n\t\t\t\ttemplateKey,\n\t\t\t\t`--folder=${folderID}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should create cascade policy (command alias)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\t});\n\n\tdescribe('metadata-templates:get', function () {\n\t\tlet scope = 'enterprise',\n\t\t\ttemplateKey = 'testTemplate',\n\t\t\tfixture = getFixture(\n\t\t\t\t'metadata-templates/get_metadata_templates_scope_template_schema'\n\t\t\t),\n\t\t\tyamlOutput = getFixture('output/metadata_templates_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/metadata_templates/${scope}/${templateKey}/schema`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-templates:get',\n\t\t\t\ttemplateKey,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information about a metadata template (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/metadata_templates/${scope}/${templateKey}/schema`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['metadata-templates:get', templateKey, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a metadata template (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('metadata-templates:delete', function () {\n\t\tlet scope = 'enterprise',\n\t\t\ttemplateKey = 'testTemplate';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(\n\t\t\t\t\t`/2.0/metadata_templates/${scope}/${templateKey}/schema`\n\t\t\t\t)\n\t\t\t\t.reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['metadata-templates:delete', templateKey, '--token=test'])\n\t\t\t.it('should delete a metadata template', (context) => {\n\t\t\t\tassert.include(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Delete metadata template with scope ${scope} and identifier ${templateKey}`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tleche.withData(\n\t\t['metadata-templates', 'metadata-templates:list'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet scope = 'enterprise',\n\t\t\t\t\tfixture = getFixture(\n\t\t\t\t\t\t'metadata-templates/get_metadata_templates_scope_page_1'\n\t\t\t\t\t),\n\t\t\t\t\tfixture2 = getFixture(\n\t\t\t\t\t\t'metadata-templates/get_metadata_templates_scope_page_2'\n\t\t\t\t\t),\n\t\t\t\t\tjsonOutput = getFixture(\n\t\t\t\t\t\t'output/metadata_templates_list_json.txt'\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/metadata_templates/${scope}`)\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t.get(`/2.0/metadata_templates/${scope}`)\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\tmarker: 'ZDFARAFD',\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, '--json', '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should get all metadata templates in your Enterprise (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tdescribe('metadata-templates:create', function () {\n\t\tlet displayName = 'New Metadata Template',\n\t\t\ttemplateKey = 'newMetadata',\n\t\t\tfixture = getFixture(\n\t\t\t\t'metadata-templates/post_metadata_templates_schema'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/metadata_templates_create_yaml.txt'\n\t\t\t);\n\n\t\tlet expectedBody = {\n\t\t\tscope: 'enterprise',\n\t\t\tdisplayName,\n\t\t\tfields: [],\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/metadata_templates/schema', {\n\t\t\t\t\t...expectedBody,\n\t\t\t\t\ttemplateKey,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-templates:create',\n\t\t\t\t`--display-name=${displayName}`,\n\t\t\t\t`--template-key=${templateKey}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a new metadata template (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/metadata_templates/schema', {\n\t\t\t\t\t...expectedBody,\n\t\t\t\t\ttemplateKey,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-templates:create',\n\t\t\t\t`--display-name=${displayName}`,\n\t\t\t\t`--template-key=${templateKey}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a new metadata template (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/metadata_templates/schema', {\n\t\t\t\t\t...expectedBody,\n\t\t\t\t\ttemplateKey,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-templates:create',\n\t\t\t\t`--display-name=${displayName}`,\n\t\t\t\t`--template-key=${templateKey}`,\n\t\t\t\t'--id-only',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a new metadata template (ID Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.parse(fixture).id}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/metadata_templates/schema', {\n\t\t\t\t\t...expectedBody,\n\t\t\t\t\thidden: true,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-templates:create',\n\t\t\t\t`--display-name=${displayName}`,\n\t\t\t\t'--hidden',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send hidden param when --hidden flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/metadata_templates/schema', {\n\t\t\t\t\t...expectedBody,\n\t\t\t\t\ttemplateKey,\n\t\t\t\t\thidden: true,\n\t\t\t\t\tcopyInstanceOnItemCopy: true,\n\t\t\t\t\tfields: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'string',\n\t\t\t\t\t\t\tdisplayName: 'Full Name',\n\t\t\t\t\t\t\thidden: false,\n\t\t\t\t\t\t\tkey: 'name',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'date',\n\t\t\t\t\t\t\tdisplayName: 'Birthday',\n\t\t\t\t\t\t\tkey: 'bday',\n\t\t\t\t\t\t\thidden: true,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'enum',\n\t\t\t\t\t\t\tdisplayName: 'State of Residence',\n\t\t\t\t\t\t\tkey: 'state',\n\t\t\t\t\t\t\tdescription: 'Where does this person live?',\n\t\t\t\t\t\t\toptions: [\n\t\t\t\t\t\t\t\t{ key: 'WI' },\n\t\t\t\t\t\t\t\t{ key: 'CA' },\n\t\t\t\t\t\t\t\t{ key: 'NY' },\n\t\t\t\t\t\t\t],\n\t\t\t\t\t\t\thidden: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'multiSelect',\n\t\t\t\t\t\t\tdisplayName: 'Programming Languages',\n\t\t\t\t\t\t\toptions: [{ key: 'Python' }, { key: 'Java' }],\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'float',\n\t\t\t\t\t\t\tdisplayName: 'Age',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-templates:create',\n\t\t\t\t`--display-name=${displayName}`,\n\t\t\t\t'--hidden',\n\t\t\t\t`--template-key=${templateKey}`,\n\t\t\t\t'--string=Full Name',\n\t\t\t\t'--no-hidden',\n\t\t\t\t'--field-key=name',\n\t\t\t\t'--date=Birthday',\n\t\t\t\t'--field-key=bday',\n\t\t\t\t'--hidden',\n\t\t\t\t'--enum=State of Residence',\n\t\t\t\t'--field-key=state',\n\t\t\t\t'--description=Where does this person live?',\n\t\t\t\t'--option=WI',\n\t\t\t\t'--option=CA',\n\t\t\t\t'--no-hidden',\n\t\t\t\t'--option=NY',\n\t\t\t\t'--multi-select=Programming Languages',\n\t\t\t\t'--option=Python',\n\t\t\t\t'--option=Java',\n\t\t\t\t'--number=Age',\n\t\t\t\t'--copy-instance-on-item-copy',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should correctly parse field declarations');\n\n\t\tleche.withData(\n\t\t\t{\n\t\t\t\t'--field-key flag outside of field deifnition': [\n\t\t\t\t\t['--field-key=foo', '--string=Name'],\n\t\t\t\t\t'Unexpected --field-key flag outside of field definition',\n\t\t\t\t],\n\t\t\t\t'--description flag outside of field definition': [\n\t\t\t\t\t['--description=foo', '--string=Name'],\n\t\t\t\t\t'Unexpected --description flag outside of field definition',\n\t\t\t\t],\n\t\t\t\t'--option flag outside of field definition': [\n\t\t\t\t\t['--option=foo', '--string=Name'],\n\t\t\t\t\t'Unexpected --option flag outside of field definition',\n\t\t\t\t],\n\t\t\t\t'--option flag in incorrect field type': [\n\t\t\t\t\t['--string=Name', '--option=foo'],\n\t\t\t\t\t'--option flag can only be specified for enum and multi-select fields',\n\t\t\t\t],\n\t\t\t},\n\t\t\tfunction (flags, expectedErrorMessage) {\n\t\t\t\ttest.stdout()\n\t\t\t\t\t.stderr()\n\t\t\t\t\t.command([\n\t\t\t\t\t\t'metadata-templates:create',\n\t\t\t\t\t\t`--display-name=${displayName}`,\n\t\t\t\t\t\t...flags,\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it('should output correct error message', (context) => {\n\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t\t`${expectedErrorMessage}${os.EOL}`\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t}\n\t\t);\n\t});\n\n\tdescribe('metadata-templates:update', function () {\n\t\tlet scope = 'enterprise',\n\t\t\ttemplateKey = 'employeeRecord',\n\t\t\tfixture = getFixture(\n\t\t\t\t'metadata-templates/put_metadata_templates_scope_key_schema_200'\n\t\t\t);\n\n\t\tlet expectedUpdates = [\n\t\t\t{\n\t\t\t\top: 'editTemplate',\n\t\t\t\tdata: {\n\t\t\t\t\thidden: true,\n\t\t\t\t\tdisplayName: 'New Display Name',\n\t\t\t\t\tcopyInstanceOnItemCopy: false,\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'addEnumOption',\n\t\t\t\tfieldKey: 'key1',\n\t\t\t\tdata: {\n\t\t\t\t\tkey: 'optionKey1',\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'addEnumOption',\n\t\t\t\tfieldKey: 'key1',\n\t\t\t\tdata: {\n\t\t\t\t\tkey: 'optionKey2',\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'addField',\n\t\t\t\tdata: {\n\t\t\t\t\ttype: 'enum',\n\t\t\t\t\tdisplayName: 'Field Display Name',\n\t\t\t\t\tdescription: 'My New Field',\n\t\t\t\t\tkey: 'key2',\n\t\t\t\t\toptions: [{ key: 'opt1' }, { key: 'opt2' }],\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'reorderEnumOptions',\n\t\t\t\tfieldKey: 'key2',\n\t\t\t\tenumOptionKeys: ['opt2', 'opt1'],\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'reorderFields',\n\t\t\t\tfieldKeys: ['key2', 'key3', 'key1'],\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'editField',\n\t\t\t\tfieldKey: 'key2',\n\t\t\t\tdata: {\n\t\t\t\t\tdisplayName: 'Different Display Name',\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'editEnumOption',\n\t\t\t\tfieldKey: 'key2',\n\t\t\t\tenumOptionKey: 'opt2',\n\t\t\t\tdata: {\n\t\t\t\t\tkey: 'newOpt2',\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'removeEnumOption',\n\t\t\t\tfieldKey: 'key2',\n\t\t\t\tenumOptionKey: 'opt1',\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'removeField',\n\t\t\t\tfieldKey: 'key2',\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'addField',\n\t\t\t\tdata: {\n\t\t\t\t\ttype: 'multiSelect',\n\t\t\t\t\tdisplayName: 'foo',\n\t\t\t\t\thidden: false,\n\t\t\t\t\toptions: [{ key: 'bar' }, { key: 'baz' }],\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'addMultiSelectOption',\n\t\t\t\tfieldKey: 'foo',\n\t\t\t\tdata: {\n\t\t\t\t\tkey: 'bas',\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'addField',\n\t\t\t\tdata: {\n\t\t\t\t\ttype: 'float',\n\t\t\t\t\tdisplayName: 'Count',\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\top: 'addField',\n\t\t\t\tdata: {\n\t\t\t\t\ttype: 'date',\n\t\t\t\t\tdisplayName: 'Date',\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(\n\t\t\t\t\t`/2.0/metadata_templates/${scope}/${templateKey}/schema`,\n\t\t\t\t\texpectedUpdates\n\t\t\t\t)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'metadata-templates:update',\n\t\t\t\ttemplateKey,\n\t\t\t\t`--scope=${scope}`,\n\t\t\t\t'--hidden',\n\t\t\t\t'--display-name=New Display Name',\n\t\t\t\t'--no-copy-instance-on-item-copy',\n\t\t\t\t'--add-enum-option=key1',\n\t\t\t\t'--option=optionKey1',\n\t\t\t\t'--option=optionKey2',\n\t\t\t\t'--enum=Field Display Name',\n\t\t\t\t'--description=My New Field',\n\t\t\t\t'--field-key=key2',\n\t\t\t\t'--option=opt1',\n\t\t\t\t'--option=opt2',\n\t\t\t\t'--reorder-enum-options=key2',\n\t\t\t\t'--option=opt2',\n\t\t\t\t'--option=opt1',\n\t\t\t\t'--reorder-fields=key2,key3,key1',\n\t\t\t\t'--edit-field=key2',\n\t\t\t\t'--display-name=Different Display Name',\n\t\t\t\t'--edit-enum-option=key2.opt2',\n\t\t\t\t'--option=newOpt2',\n\t\t\t\t'--remove-enum-option=key2.opt1',\n\t\t\t\t'--remove-field=key2',\n\t\t\t\t'--multi-select=foo',\n\t\t\t\t'--option=bar',\n\t\t\t\t'--option=baz',\n\t\t\t\t'--no-hidden',\n\t\t\t\t'--add-multi-select-option=foo',\n\t\t\t\t'--option=bas',\n\t\t\t\t'--number=Count',\n\t\t\t\t'--date=Date',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update the metadata template (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\tleche.withData(\n\t\t\t{\n\t\t\t\t'hidden flag in wrong location': [\n\t\t\t\t\t['--remove-field=key2', '--hidden'],\n\t\t\t\t\t'Unexpected --hidden flag outside of template or field edit operation',\n\t\t\t\t],\n\t\t\t\t'malformed option key in --edit-enum-option flag': [\n\t\t\t\t\t['--edit-enum-option=key-option'],\n\t\t\t\t\t'Enum option key must be formatted as fieldKey.optionKey',\n\t\t\t\t],\n\t\t\t\t'malformed option key in --remove-enum-option flag': [\n\t\t\t\t\t['--remove-enum-option=key-option'],\n\t\t\t\t\t'Enum option key must be formatted as fieldKey.optionKey',\n\t\t\t\t],\n\t\t\t\t'--option flag before any field operation': [\n\t\t\t\t\t['--option=foo'],\n\t\t\t\t\t'Unexpected --option flag outside of option-related operation',\n\t\t\t\t],\n\t\t\t\t'--option flag in unrelated operation': [\n\t\t\t\t\t['--edit-field=bar', '--option=opt'],\n\t\t\t\t\t'Unexpected --option flag outside of option-related operation',\n\t\t\t\t],\n\t\t\t\t'--option flag in incorrect field type': [\n\t\t\t\t\t['--string=Name', '--option=John Doe'],\n\t\t\t\t\t'Unexpected --option flag while specifying string field',\n\t\t\t\t],\n\t\t\t\t'--field-key flag outside of operation group': [\n\t\t\t\t\t['--field-key=quux'],\n\t\t\t\t\t'Unexpected --field-key flag outside of field operation',\n\t\t\t\t],\n\t\t\t\t'--field-key flag in incorrect operation group': [\n\t\t\t\t\t['--reorder-enum-options=foo', '--field-key=bar'],\n\t\t\t\t\t'Unexpected --field-key flag outside of field add or edit operation',\n\t\t\t\t],\n\t\t\t\t'--description flag outside of field operation': [\n\t\t\t\t\t['--description=Blah'],\n\t\t\t\t\t'Unexpected --description flag outside of field operation',\n\t\t\t\t],\n\t\t\t\t'--display-name field in incorrect operation group': [\n\t\t\t\t\t['--reorder-enum-options=foo', '--display-name=Wrong!'],\n\t\t\t\t\t'Unexpected --display-name flag outside of template or field edit operation',\n\t\t\t\t],\n\t\t\t\t'--copy-instance-on-item-copy flag in incorrect operation group':\n\t\t\t\t\t[\n\t\t\t\t\t\t['--edit-field=bar', '--copy-instance-on-item-copy'],\n\t\t\t\t\t\t'Unexpected --copy-instance-on-item-copy flag outside of template edit operation',\n\t\t\t\t\t],\n\t\t\t},\n\t\t\tfunction (flags, expectedErrorMessage) {\n\t\t\t\ttest.stdout()\n\t\t\t\t\t.stderr()\n\t\t\t\t\t.command([\n\t\t\t\t\t\t'metadata-templates:update',\n\t\t\t\t\t\ttemplateKey,\n\t\t\t\t\t\t`--scope=${scope}`,\n\t\t\t\t\t\t...flags,\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it('should output correct error message', (context) => {\n\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t\t`${expectedErrorMessage}${os.EOL}`\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t}\n\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/recent-items.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst { assert } = require('chai');\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\n\ndescribe('Recent Items', function () {\n\tdescribe('recent-items', function () {\n\t\tlet fixture = getFixture('recent-items/get_recent_items_page_1'),\n\t\t\tfixture2 = getFixture('recent-items/get_recent_items_page_2'),\n\t\t\tjsonOutput = getFixture('output/recent_items_json.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/recent_items')\n\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/recent_items')\n\t\t\t\t.query({\n\t\t\t\t\tmarker: 'ZDF123',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['recent-items', '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should list information about files accessed in the past 90 days up to a 1000 items (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/recent_items')\n\t\t\t\t.query({ fields: 'name', limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/recent_items')\n\t\t\t\t.query({\n\t\t\t\t\tfields: 'name',\n\t\t\t\t\tmarker: 'ZDF123',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'recent-items',\n\t\t\t\t'--fields=name',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/request.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst { assert } = require('chai');\nconst { TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\nconst crypto = require('node:crypto');\n\ndescribe('Manual Request', function () {\n\tdescribe('request', function () {\n\t\tlet fixture = `{}${os.EOL}`,\n\t\t\tjsonBody = {\n\t\t\t\tfoo: 'bar',\n\t\t\t\tbaz: 123.456,\n\t\t\t},\n\t\t\tbufferBody = crypto.randomFillSync(Buffer.alloc(10));\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get('/2.0/widgets').reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['request', '/widgets', '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should make simple GET request when resource given as path (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedObject = {\n\t\t\t\t\t\tstatusCode: 200,\n\t\t\t\t\t\theaders: {},\n\t\t\t\t\t\tbody: {},\n\t\t\t\t\t};\n\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.stringify(expectedObject, null, 4)}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get('/2.0/widgets').reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['request', '/widgets', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should make simple GET request when resource given as path (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet lb = '\\n';\n\t\t\t\t\tlet expectedOutput = `Status Code: 200${lb}Headers: {}${lb}Body: {}${os.EOL}`;\n\n\t\t\t\t\tassert.equal(context.stdout, expectedOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get('/2.0/widgets').reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'request',\n\t\t\t\t'https://api.box.com/2.0/widgets',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should make simple GET request when resource given as URL',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedObject = {\n\t\t\t\t\t\tstatusCode: 200,\n\t\t\t\t\t\theaders: {},\n\t\t\t\t\t\tbody: {},\n\t\t\t\t\t};\n\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.stringify(expectedObject, null, 4)}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/widgets')\n\t\t\t\t.matchHeader('X-Box-Header', 'foo=bar')\n\t\t\t\t.matchHeader('X-Box-Header2', 'baz quux')\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'request',\n\t\t\t\t'https://api.box.com/2.0/widgets',\n\t\t\t\t'--header=X-Box-Header: foo=bar',\n\t\t\t\t'-HX-Box-Header2: baz quux',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send request headers when header flags are passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedObject = {\n\t\t\t\t\t\tstatusCode: 200,\n\t\t\t\t\t\theaders: {},\n\t\t\t\t\t\tbody: {},\n\t\t\t\t\t};\n\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.stringify(expectedObject, null, 4)}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/widgets')\n\t\t\t\t.query({\n\t\t\t\t\tfoo: 'bar==bar',\n\t\t\t\t\tbaz: 'quux slod quop',\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'request',\n\t\t\t\t'https://api.box.com/2.0/widgets',\n\t\t\t\t'--query=foo=bar%3D%3Dbar&baz=quux slod%20quop',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send query params when --query flag is passed in key=value format',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedObject = {\n\t\t\t\t\t\tstatusCode: 200,\n\t\t\t\t\t\theaders: {},\n\t\t\t\t\t\tbody: {},\n\t\t\t\t\t};\n\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.stringify(expectedObject, null, 4)}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/widgets')\n\t\t\t\t.query({\n\t\t\t\t\tfoo: 'bar==bar',\n\t\t\t\t\tbaz: 'quux slod quop',\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'request',\n\t\t\t\t'https://api.box.com/2.0/widgets',\n\t\t\t\t'--query={\"foo\":\"bar==bar\",\"baz\":\"quux slod quop\"}',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send query params when --query flag is passed in JSON format',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedObject = {\n\t\t\t\t\t\tstatusCode: 200,\n\t\t\t\t\t\theaders: {},\n\t\t\t\t\t\tbody: {},\n\t\t\t\t\t};\n\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.stringify(expectedObject, null, 4)}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/widgets', jsonBody)\n\t\t\t\t.matchHeader('Content-Type', 'application/json')\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'request',\n\t\t\t\t'https://api.box.com/2.0/widgets',\n\t\t\t\t'--method=POST',\n\t\t\t\t`--body=${JSON.stringify(jsonBody)}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send request body when --body flag is passed in JSON format',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedObject = {\n\t\t\t\t\t\tstatusCode: 201,\n\t\t\t\t\t\theaders: {},\n\t\t\t\t\t\tbody: {},\n\t\t\t\t\t};\n\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.stringify(expectedObject, null, 4)}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(\n\t\t\t\t\t'/2.0/widgets',\n\t\t\t\t\t(body) => body === bufferBody.toString('utf8')\n\t\t\t\t)\n\t\t\t\t.matchHeader('Content-Type', 'application/octet-stream')\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'request',\n\t\t\t\t'https://api.box.com/2.0/widgets',\n\t\t\t\t'-XPOST',\n\t\t\t\t`--body=${bufferBody.toString('utf8')}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send request body when --body flag is passed in non-JSON format',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedObject = {\n\t\t\t\t\t\tstatusCode: 201,\n\t\t\t\t\t\theaders: {},\n\t\t\t\t\t\tbody: {},\n\t\t\t\t\t};\n\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.stringify(expectedObject, null, 4)}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(\n\t\t\t\t\t'/2.0/widgets/123',\n\t\t\t\t\t(body) => body === bufferBody.toString('hex')\n\t\t\t\t)\n\t\t\t\t.matchHeader('Content-Type', 'text/plain')\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'request',\n\t\t\t\t'/widgets/123',\n\t\t\t\t'-XPUT',\n\t\t\t\t`--body=${bufferBody.toString('hex')}`,\n\t\t\t\t'--header=Content-Type: text/plain',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should allow overriding Content-Type header when both --body and --header flags are passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedObject = {\n\t\t\t\t\t\tstatusCode: 200,\n\t\t\t\t\t\theaders: {},\n\t\t\t\t\t\tbody: {},\n\t\t\t\t\t};\n\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.stringify(expectedObject, null, 4)}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.delete('/2.0/widgets/123').reply(204)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'request',\n\t\t\t\t'/widgets/123',\n\t\t\t\t'-XDELETE',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should allow DELETE request when method is set to DELETE',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedObject = {\n\t\t\t\t\t\tstatusCode: 204,\n\t\t\t\t\t\theaders: {},\n\t\t\t\t\t};\n\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.stringify(expectedObject, null, 4)}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.options('/2.0/widgets').reply(204)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'request',\n\t\t\t\t'/widgets',\n\t\t\t\t'-XOPTIONS',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should allow OPTIONS request when method is set to OPTIONS',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedObject = {\n\t\t\t\t\t\tstatusCode: 204,\n\t\t\t\t\t\theaders: {},\n\t\t\t\t\t};\n\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.stringify(expectedObject, null, 4)}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/retention-policies.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst { assert } = require('chai');\nconst leche = require('leche');\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\n\ndescribe('Retention Policies', function () {\n\tdescribe('retention-policies:create', function () {\n\t\tlet policyName = 'Financial Records',\n\t\t\tretentionLength = 365,\n\t\t\tdispositionAction = 'remove_retention',\n\t\t\tretentionType = 'modifiable',\n\t\t\tfixture = getFixture('retention-policies/post_retention_policies'),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/retention_policies_create_yaml.txt'\n\t\t\t);\n\n\t\tlet expectedBody = {\n\t\t\tpolicy_name: policyName,\n\t\t\tdisposition_action: dispositionAction,\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/retention_policies', {\n\t\t\t\t\t...expectedBody,\n\t\t\t\t\tpolicy_type: 'finite',\n\t\t\t\t\tretention_length: retentionLength,\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:create',\n\t\t\t\tpolicyName,\n\t\t\t\t`--disposition-action=${dispositionAction}`,\n\t\t\t\t`--retention-length=${retentionLength}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a new retention policy with the retention-length flag passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/retention_policies', {\n\t\t\t\t\t...expectedBody,\n\t\t\t\t\tpolicy_type: 'finite',\n\t\t\t\t\tretention_length: retentionLength,\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:create',\n\t\t\t\tpolicyName,\n\t\t\t\t`--disposition-action=${dispositionAction}`,\n\t\t\t\t`--retention-length=${retentionLength}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a new retention policy with the retention-length flag passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/retention_policies', {\n\t\t\t\t\t...expectedBody,\n\t\t\t\t\tpolicy_type: 'indefinite',\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:create',\n\t\t\t\tpolicyName,\n\t\t\t\t`--disposition-action=${dispositionAction}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create an indefinite retention policy when indefinite arg is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/retention_policies', {\n\t\t\t\t\t...expectedBody,\n\t\t\t\t\tpolicy_type: 'finite',\n\t\t\t\t\tretention_length: retentionLength,\n\t\t\t\t\tretention_type: retentionType,\n\t\t\t\t\tare_owners_notified: true,\n\t\t\t\t\tcan_owner_extend_retention: true,\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:create',\n\t\t\t\tpolicyName,\n\t\t\t\t`--disposition-action=${dispositionAction}`,\n\t\t\t\t`--retention-length=${retentionLength}`,\n\t\t\t\t`--retention-type=${retentionType}`,\n\t\t\t\t'--notify-owners',\n\t\t\t\t'--allow-extension',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send optional params when flags are passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/retention_policies', {\n\t\t\t\t\t...expectedBody,\n\t\t\t\t\tpolicy_type: 'finite',\n\t\t\t\t\tretention_length: retentionLength,\n\t\t\t\t\tdescription: 'This is a description',\n\t\t\t\t\tcustom_notification_recipients: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'user',\n\t\t\t\t\t\t\tid: '12345',\n\t\t\t\t\t\t\tlogin: 'user@box.com',\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'user',\n\t\t\t\t\t\t\tid: '34567',\n\t\t\t\t\t\t\tlogin: 'user2@box.com',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:create',\n\t\t\t\tpolicyName,\n\t\t\t\t`--disposition-action=${dispositionAction}`,\n\t\t\t\t`--retention-length=${retentionLength}`,\n\t\t\t\t'--description=This is a description',\n\t\t\t\t'--custom-notification-recipient=id=12345,login=user@box.com',\n\t\t\t\t'--custom-notification-recipient=id=34567,login=user2@box.com',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a new retention policy with custom description and custom notification recipients',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('retention-policies:update', function () {\n\t\tlet policyId = '11111',\n\t\t\tname = 'Retained Financial Records',\n\t\t\tdispositionAction = 'permanently_delete',\n\t\t\tpolicyType = 'finite',\n\t\t\tretentionLength = 500,\n\t\t\tretentionType = 'non_modifiable',\n\t\t\tfixture = getFixture(\n\t\t\t\t'retention-policies/put_retention_policies_id'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/retention_policies_update_yaml.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/retention_policies/${policyId}`, {\n\t\t\t\t\tpolicy_name: name,\n\t\t\t\t\tstatus: 'retired',\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:update',\n\t\t\t\tpolicyId,\n\t\t\t\t`--policy-name=${name}`,\n\t\t\t\t'-r',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a retention policy with policy-name and retire flags passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/retention_policies/${policyId}`, {\n\t\t\t\t\tpolicy_name: name,\n\t\t\t\t\tstatus: 'retired',\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:update',\n\t\t\t\tpolicyId,\n\t\t\t\t`--policy-name=${name}`,\n\t\t\t\t'-r',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a retention policy with policy-name and retire flags passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/retention_policies/${policyId}`, {\n\t\t\t\t\tdisposition_action: dispositionAction,\n\t\t\t\t\tpolicy_type: policyType,\n\t\t\t\t\tretention_length: retentionLength,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:update',\n\t\t\t\tpolicyId,\n\t\t\t\t`--disposition-action=${dispositionAction}`,\n\t\t\t\t`--policy-type=${policyType}`,\n\t\t\t\t`--retention-length=${retentionLength}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update policy type, disposition, and length when appropriate flags are passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/retention_policies/${policyId}`, {\n\t\t\t\t\tretention_type: retentionType,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:update',\n\t\t\t\tpolicyId,\n\t\t\t\t'--non-modifiable',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update retention type when appropriate flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('retention-policies:get', function () {\n\t\tlet policyId = '11111',\n\t\t\tfixture = getFixture(\n\t\t\t\t'retention-policies/get_retention_policies_id'\n\t\t\t),\n\t\t\tyamlOutput = getFixture('output/retention_policies_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/retention_policies/${policyId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:get',\n\t\t\t\tpolicyId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information about a retention policy (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/retention_policies/${policyId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['retention-policies:get', policyId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a retention policy (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/retention_policies/${policyId}`)\n\t\t\t\t.query({ fields: 'disposition_action' })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:get',\n\t\t\t\tpolicyId,\n\t\t\t\t'--fields=disposition_action',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('retention-policies', function () {\n\t\tlet policyName = 'test',\n\t\t\tpolicyType = 'indefinite',\n\t\t\tcreatorID = '12345',\n\t\t\tfixture = getFixture(\n\t\t\t\t'retention-policies/get_retention_policies_page_1'\n\t\t\t),\n\t\t\tfixture2 = getFixture(\n\t\t\t\t'retention-policies/get_retention_policies_page_2'\n\t\t\t),\n\t\t\tjsonOutput = getFixture('output/retention_policies_list_json.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/retention_policies')\n\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/retention_policies')\n\t\t\t\t.query({\n\t\t\t\t\tmarker: 'ZDE345',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['retention-policies', '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should list all retention policies (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/retention_policies')\n\t\t\t\t.query({\n\t\t\t\t\tfields: 'policy_name',\n\t\t\t\t\tpolicy_name: policyName,\n\t\t\t\t\tpolicy_type: policyType,\n\t\t\t\t\tcreated_by_user_id: creatorID,\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/retention_policies')\n\t\t\t\t.query({\n\t\t\t\t\tfields: 'policy_name',\n\t\t\t\t\tpolicy_name: policyName,\n\t\t\t\t\tpolicy_type: policyType,\n\t\t\t\t\tcreated_by_user_id: creatorID,\n\t\t\t\t\tmarker: 'ZDE345',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies',\n\t\t\t\t`--policy-name=${policyName}`,\n\t\t\t\t`--policy-type=${policyType}`,\n\t\t\t\t`--created-by-user-id=${creatorID}`,\n\t\t\t\t'--fields=policy_name',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send optional params when flags are passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('retention-policies:assignments:get', function () {\n\t\tlet assignmentId = '12345',\n\t\t\tfixture = getFixture(\n\t\t\t\t'retention-policies/get_retention_policy_assignments_id'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/retention_policies_get_assignment_yaml.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/retention_policy_assignments/${assignmentId}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:assignments:get',\n\t\t\t\tassignmentId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information about a retention policy assignment (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/retention_policy_assignments/${assignmentId}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:assignments:get',\n\t\t\t\tassignmentId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information about a retention policy assignment (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/retention_policy_assignments/${assignmentId}`)\n\t\t\t\t.query({ fields: 'assigned_to' })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:assignments:get',\n\t\t\t\tassignmentId,\n\t\t\t\t'--fields=assigned_to',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('retention-policies:assignments:remove', function () {\n\t\tlet assignmentId = '123456';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(`/2.0/retention_policy_assignments/${assignmentId}`)\n\t\t\t\t.reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'retention-policies:assignments:remove',\n\t\t\t\tassignmentId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should remove a retention policy assignment', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Removed retention policy assignment ${assignmentId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tdescribe('retention-policies:assign', function () {\n\t\tlet policyId = '11111',\n\t\t\ttype = 'folder',\n\t\t\tfolderId = '22222',\n\t\t\tfixture = getFixture(\n\t\t\t\t'retention-policies/post_retention_policy_assignments'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/retention_policies_assign_yaml.txt'\n\t\t\t);\n\n\t\tlet expectedBody = {\n\t\t\tpolicy_id: policyId,\n\t\t\tassign_to: {\n\t\t\t\ttype,\n\t\t\t\tid: folderId,\n\t\t\t},\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/retention_policy_assignments', expectedBody)\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:assign',\n\t\t\t\tpolicyId,\n\t\t\t\t`--assign-to-type=${type}`,\n\t\t\t\t`--assign-to-id=${folderId}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should assign a retention policy assignment (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/retention_policy_assignments', expectedBody)\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:assign',\n\t\t\t\tpolicyId,\n\t\t\t\t`--assign-to-type=${type}`,\n\t\t\t\t`--assign-to-id=${folderId}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should assign a retention policy assignment (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/retention_policy_assignments', {\n\t\t\t\t\t...expectedBody,\n\t\t\t\t\tassign_to: {\n\t\t\t\t\t\tid: null,\n\t\t\t\t\t\ttype: 'enterprise',\n\t\t\t\t\t},\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:assign',\n\t\t\t\tpolicyId,\n\t\t\t\t'--assign-to-type=enterprise',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should assign policy to the enterprise without taking an ID argument',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/retention_policy_assignments', {\n\t\t\t\t\t...expectedBody,\n\t\t\t\t\tassign_to: {\n\t\t\t\t\t\ttype: 'enterprise',\n\t\t\t\t\t\tid: null,\n\t\t\t\t\t},\n\t\t\t\t\tfilter_fields: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tfield: 'a0f4ee4e-1dc1-4h90-a8a9-aef55fc681d4',\n\t\t\t\t\t\t\tvalue: '0c27b756-0p87-4fe0-a43a-59fb661ccc4e',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tstart_date_field: 'upload_date',\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:assign',\n\t\t\t\tpolicyId,\n\t\t\t\t'--assign-to-type=enterprise',\n\t\t\t\t'--filter-field=a0f4ee4e-1dc1-4h90-a8a9-aef55fc681d4=0c27b756-0p87-4fe0-a43a-59fb661ccc4e',\n\t\t\t\t'--start-date-field=upload_date',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should assign policy to the enterprise with custom filter fields and start date field',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\t// @TODO(2018-08-21): Add test for missing ID error scenario\n\t});\n\n\tdescribe('retention-policies:assignments', function () {\n\t\tlet policyId = '11111',\n\t\t\ttype = 'metadata_template',\n\t\t\tfixture = getFixture(\n\t\t\t\t'retention-policies/get_retention_policies_id_assignments_page_1'\n\t\t\t),\n\t\t\tfixture2 = getFixture(\n\t\t\t\t'retention-policies/get_retention_policies_id_assignments_page_2'\n\t\t\t),\n\t\t\tjsonOutput = getFixture(\n\t\t\t\t'output/retention_policies_list_assignments_json.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/retention_policies/${policyId}/assignments`)\n\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get(`/2.0/retention_policies/${policyId}/assignments`)\n\t\t\t\t.query({\n\t\t\t\t\tmarker: 'ZDE456',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:assignments',\n\t\t\t\tpolicyId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should list all assignments for retention policy (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/retention_policies/${policyId}/assignments`)\n\t\t\t\t.query({ type, limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get(`/2.0/retention_policies/${policyId}/assignments`)\n\t\t\t\t.query({\n\t\t\t\t\ttype,\n\t\t\t\t\tmarker: 'ZDE456',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:assignments',\n\t\t\t\tpolicyId,\n\t\t\t\t`--type=${type}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send type param when --type flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/retention_policies/${policyId}/assignments`)\n\t\t\t\t.query({ fields: 'assigned_to', limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get(`/2.0/retention_policies/${policyId}/assignments`)\n\t\t\t\t.query({\n\t\t\t\t\tfields: 'assigned_to',\n\t\t\t\t\tmarker: 'ZDE456',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:assignments',\n\t\t\t\tpolicyId,\n\t\t\t\t'--fields=assigned_to',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('retention-policies:file-version-retentions:get', function () {\n\t\tlet retentionId = '444444',\n\t\t\tfixture = getFixture(\n\t\t\t\t'retention-policies/get_file_version_retentions_id'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/retention_policies_get_version_retention_yaml.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/file_version_retentions/${retentionId}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:file-version-retentions:get',\n\t\t\t\tretentionId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information about a file version retention policy (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/file_version_retentions/${retentionId}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:file-version-retentions:get',\n\t\t\t\tretentionId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information about a file version retention policy (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/file_version_retentions/${retentionId}`)\n\t\t\t\t.query({ fields: 'id' })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:file-version-retentions:get',\n\t\t\t\tretentionId,\n\t\t\t\t'--fields=id',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('retention-policies:file-version-retentions', function () {\n\t\tlet fixture = getFixture(\n\t\t\t\t'retention-policies/get_file_version_retentions_page_1'\n\t\t\t),\n\t\t\tfixture2 = getFixture(\n\t\t\t\t'retention-policies/get_file_version_retentions_page_2'\n\t\t\t),\n\t\t\tjsonOutput = getFixture(\n\t\t\t\t'output/retention_policies_list_version_retentions_json.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/file_version_retentions')\n\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/file_version_retentions')\n\t\t\t\t.query({\n\t\t\t\t\tmarker: 'ZAD345',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:file-version-retentions',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should list all file version retentions (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\tleche.withData(\n\t\t\t{\n\t\t\t\t'disposition action flag': [\n\t\t\t\t\t'--disposition-action=remove_retention',\n\t\t\t\t\t{ disposition_action: 'remove_retention' },\n\t\t\t\t],\n\t\t\t\t'file ID flag': ['--file-id=1234', { file_id: '1234' }],\n\t\t\t\t'file version ID flag': [\n\t\t\t\t\t'--file-version-id=9876',\n\t\t\t\t\t{ file_version_id: '9876' },\n\t\t\t\t],\n\t\t\t\t'policy ID flag': ['--policy-id=4444', { policy_id: '4444' }],\n\t\t\t\t'disposition after flag': [\n\t\t\t\t\t'--disposition-after=2024-11-07T12:34:56+00:00',\n\t\t\t\t\t{ disposition_after: '2024-11-07T12:34:56+00:00' },\n\t\t\t\t],\n\t\t\t\t'disposition before flag': [\n\t\t\t\t\t'--disposition-before=2024-11-07T12:34:56+00:00',\n\t\t\t\t\t{ disposition_before: '2024-11-07T12:34:56+00:00' },\n\t\t\t\t],\n\t\t\t\t'fields flag': ['--fields=id', { fields: 'id' }],\n\t\t\t},\n\t\t\tfunction (flag, queryParameters) {\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get('/2.0/file_version_retentions')\n\t\t\t\t\t\t.query({ ...queryParameters, limit: 1000 })\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t.get('/2.0/file_version_retentions')\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\t...queryParameters,\n\t\t\t\t\t\t\tmarker: 'ZAD345',\n\t\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\t'retention-policies:file-version-retentions',\n\t\t\t\t\t\tflag,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should pass optional parameter when flag is passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t}\n\t\t);\n\t});\n\n\tdescribe('retention-policies:files-under-retention:get', function () {\n\t\tlet policyAssignmentId = '11111',\n\t\t\tfixture = getFixture(\n\t\t\t\t'retention-policies/get_files_under_retention_page_1'\n\t\t\t),\n\t\t\tfixture2 = getFixture(\n\t\t\t\t'retention-policies/get_files_under_retention_page_2'\n\t\t\t),\n\t\t\tjsonOutput = getFixture(\n\t\t\t\t'output/retention_policies_get_files_under_retention_json.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(\n\t\t\t\t\t`/2.0/retention_policy_assignments/${policyAssignmentId}/files_under_retention`\n\t\t\t\t)\n\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get(\n\t\t\t\t\t`/2.0/retention_policy_assignments/${policyAssignmentId}/files_under_retention`\n\t\t\t\t)\n\t\t\t\t.query({\n\t\t\t\t\tmarker: 'ZAD345',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:files-under-retention:get',\n\t\t\t\tpolicyAssignmentId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should list all files under retention for assignment  (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('retention-policies:file-versions-under-retention:get', function () {\n\t\tlet policyAssignmentId = '11111',\n\t\t\tfixture = getFixture(\n\t\t\t\t'retention-policies/get_file_versions_under_retention_page_1'\n\t\t\t),\n\t\t\tfixture2 = getFixture(\n\t\t\t\t'retention-policies/get_file_versions_under_retention_page_2'\n\t\t\t),\n\t\t\tjsonOutput = getFixture(\n\t\t\t\t'output/retention_policies_get_file_versions_under_retention_json.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(\n\t\t\t\t\t`/2.0/retention_policy_assignments/${policyAssignmentId}/file_versions_under_retention`\n\t\t\t\t)\n\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get(\n\t\t\t\t\t`/2.0/retention_policy_assignments/${policyAssignmentId}/file_versions_under_retention`\n\t\t\t\t)\n\t\t\t\t.query({\n\t\t\t\t\tmarker: 'ZAD345',\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'retention-policies:file-versions-under-retention:get',\n\t\t\t\tpolicyAssignmentId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should list all file versions under retention for assignment (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/search.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst { assert } = require('chai');\nconst {\n\tgetFixture,\n\tTEST_API_ROOT,\n\tgetBulkProgressBar,\n} = require('../helpers/test-helper');\nconst leche = require('leche');\nconst os = require('node:os');\nconst path = require('node:path');\n\ndescribe('Search', function () {\n\tlet query = 'Test',\n\t\tbulkInputFilePath = path.join(\n\t\t\t__dirname,\n\t\t\t'../fixtures/search/bulk/bulk_get_search_query_input.csv'\n\t\t),\n\t\tfixture = getFixture('search/get_search_query_page_1'),\n\t\tfixture2 = getFixture('search/get_search_query_page_2'),\n\t\tjsonOutput = getFixture('output/search_json.txt'),\n\t\tjsonOutputLimitedTo5 = getFixture('output/search_json_limit_5.txt');\n\n\tdescribe('search', function () {\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/search')\n\t\t\t\t.query({\n\t\t\t\t\tquery,\n\t\t\t\t\tlimit: 100,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/search')\n\t\t\t\t.query({\n\t\t\t\t\tquery,\n\t\t\t\t\tlimit: 100,\n\t\t\t\t\toffset: 5,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['search', query, '--json', '--token=test'])\n\t\t\t.it('should search with query (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/search')\n\t\t\t\t.query({\n\t\t\t\t\tquery,\n\t\t\t\t\tfields: 'name',\n\t\t\t\t\tlimit: 100,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/search')\n\t\t\t\t.query({\n\t\t\t\t\tquery,\n\t\t\t\t\tfields: 'name',\n\t\t\t\t\tlimit: 100,\n\t\t\t\t\toffset: 5,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'search',\n\t\t\t\tquery,\n\t\t\t\t'--fields=name',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/search')\n\t\t\t\t.query({\n\t\t\t\t\tlimit: 100,\n\t\t\t\t\tquery: '',\n\t\t\t\t\tmdfilters:\n\t\t\t\t\t\t'[{\"scope\":\"enterprise\",\"templateKey\":\"marketingCollateral\",\"filters\":{\"key\":\"value\"}}]',\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/search')\n\t\t\t\t.query({\n\t\t\t\t\tmdfilters:\n\t\t\t\t\t\t'[{\"scope\":\"enterprise\",\"templateKey\":\"marketingCollateral\",\"filters\":{\"key\":\"value\"}}]',\n\t\t\t\t\tlimit: 100,\n\t\t\t\t\tquery: '',\n\t\t\t\t\toffset: 5,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'search',\n\t\t\t\t'--md-filter-scope=enterprise',\n\t\t\t\t'--md-filter-template-key=marketingCollateral',\n\t\t\t\t'--md-filter-json={\"key\":\"value\"}',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should search for files and folders in your Enterprise with NO QUERY and md-filter-scope, md-filter-template-key, md-filter-json flags passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\tleche.withData(\n\t\t\t{\n\t\t\t\t'scope flag set to user content': [\n\t\t\t\t\t['--scope=user_content'],\n\t\t\t\t\t{ scope: 'user_content' },\n\t\t\t\t],\n\t\t\t\t'scope flag set to enterprise content': [\n\t\t\t\t\t['--scope=enterprise_content'],\n\t\t\t\t\t{ scope: 'enterprise_content' },\n\t\t\t\t],\n\t\t\t\t'type flag set to file': [['--type=file'], { type: 'file' }],\n\t\t\t\t'type flag set to folder': [\n\t\t\t\t\t['--type=folder'],\n\t\t\t\t\t{ type: 'folder' },\n\t\t\t\t],\n\t\t\t\t'file extensions flag with one extension': [\n\t\t\t\t\t['--file-extensions=pdf'],\n\t\t\t\t\t{ file_extensions: 'pdf' },\n\t\t\t\t],\n\t\t\t\t'file extensions flags set to multiple extensions': [\n\t\t\t\t\t['--file-extensions=doc,docx,xls'],\n\t\t\t\t\t{ file_extensions: 'doc,docx,xls' },\n\t\t\t\t],\n\t\t\t\t'content types flag set to one type': [\n\t\t\t\t\t['--content-types=name'],\n\t\t\t\t\t{ content_types: 'name' },\n\t\t\t\t],\n\t\t\t\t'content types flag set to multiple content types': [\n\t\t\t\t\t['--content-types=name,description'],\n\t\t\t\t\t{ content_types: 'name,description' },\n\t\t\t\t],\n\t\t\t\t'ancestor folder IDs flag': [\n\t\t\t\t\t['--ancestor-folder-ids=123,456,789'],\n\t\t\t\t\t{ ancestor_folder_ids: '123,456,789' },\n\t\t\t\t],\n\t\t\t\t'owner user IDs flag': [\n\t\t\t\t\t['--owner-user-ids=987,654,321'],\n\t\t\t\t\t{ owner_user_ids: '987,654,321' },\n\t\t\t\t],\n\t\t\t\t'trash content flag set to trash': [\n\t\t\t\t\t['--trash-content=trashed_only'],\n\t\t\t\t\t{ trash_content: 'trashed_only' },\n\t\t\t\t],\n\t\t\t\t'trash content flag set to non-trash': [\n\t\t\t\t\t['--trash-content=non_trashed_only'],\n\t\t\t\t\t{ trash_content: 'non_trashed_only' },\n\t\t\t\t],\n\t\t\t\t'size from flag': [['--size-from=150'], { size_range: '150,' }],\n\t\t\t\t'size to flag': [['--size-to=1024'], { size_range: ',1024' }],\n\t\t\t\t'size from and size to flags': [\n\t\t\t\t\t['--size-from=1024', '--size-to=4096'],\n\t\t\t\t\t{ size_range: '1024,4096' },\n\t\t\t\t],\n\t\t\t\t'created and updated timestamp flags': [\n\t\t\t\t\t[\n\t\t\t\t\t\t'--created-at-from=2018-01-01T00:00:00+00:00',\n\t\t\t\t\t\t'--created-at-to=2018-12-31T23:59:59+00:00',\n\t\t\t\t\t\t'--updated-at-from=2019-01-01T00:00:00+00:00',\n\t\t\t\t\t\t'--updated-at-to=2019-12-31T23:59:59+00:00',\n\t\t\t\t\t],\n\t\t\t\t\t{\n\t\t\t\t\t\tcreated_at_range:\n\t\t\t\t\t\t\t'2018-01-01T00:00:00+00:00,2018-12-31T23:59:59+00:00',\n\t\t\t\t\t\tupdated_at_range:\n\t\t\t\t\t\t\t'2019-01-01T00:00:00+00:00,2019-12-31T23:59:59+00:00',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'sort order flags': [\n\t\t\t\t\t['--sort=modified_at', '--direction=asc'],\n\t\t\t\t\t{\n\t\t\t\t\t\tsort: 'modified_at',\n\t\t\t\t\t\tdirection: 'asc',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'multitple metadata filters': [\n\t\t\t\t\t[\n\t\t\t\t\t\t'--md-filter-scope=global',\n\t\t\t\t\t\t'--md-filter-template-key=properties',\n\t\t\t\t\t\t'--md-filter-json={\"foo\":\"bar\"}',\n\t\t\t\t\t\t'--md-filter-scope=enterprise',\n\t\t\t\t\t\t'--md-filter-template-key=myTemplate',\n\t\t\t\t\t\t'--md-filter-json={\"baz\":\"quux\"}',\n\t\t\t\t\t],\n\t\t\t\t\t{\n\t\t\t\t\t\tmdfilters: JSON.stringify([\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tscope: 'global',\n\t\t\t\t\t\t\t\ttemplateKey: 'properties',\n\t\t\t\t\t\t\t\tfilters: {\n\t\t\t\t\t\t\t\t\tfoo: 'bar',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tscope: 'enterprise',\n\t\t\t\t\t\t\t\ttemplateKey: 'myTemplate',\n\t\t\t\t\t\t\t\tfilters: {\n\t\t\t\t\t\t\t\t\tbaz: 'quux',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'mdfilter flag': [\n\t\t\t\t\t['--mdfilter=global.properties.foo=bar'],\n\t\t\t\t\t{\n\t\t\t\t\t\tmdfilters: JSON.stringify([\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tscope: 'global',\n\t\t\t\t\t\t\t\ttemplateKey: 'properties',\n\t\t\t\t\t\t\t\tfilters: {\n\t\t\t\t\t\t\t\t\tfoo: 'bar',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'Classification metadata filter': [\n\t\t\t\t\t[\n\t\t\t\t\t\t'--mdfilter=enterprise.securityClassification-6VMVochwUWo.Box__Security__Classification__Key=Public',\n\t\t\t\t\t],\n\t\t\t\t\t{\n\t\t\t\t\t\tmdfilters: JSON.stringify([\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tscope: 'enterprise',\n\t\t\t\t\t\t\t\ttemplateKey:\n\t\t\t\t\t\t\t\t\t'securityClassification-6VMVochwUWo',\n\t\t\t\t\t\t\t\tfilters: {\n\t\t\t\t\t\t\t\t\tBox__Security__Classification__Key:\n\t\t\t\t\t\t\t\t\t\t'Public',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'multiple mdfilter flags': [\n\t\t\t\t\t[\n\t\t\t\t\t\t'--mdfilter=global.properties.foo=barf',\n\t\t\t\t\t\t'--mdfilter=global.properties.money=3.51f',\n\t\t\t\t\t\t'--mdfilter=enterprise.myTemplate.baz=quux',\n\t\t\t\t\t\t'--mdfilter=enterprise.myTemplate.num>123f',\n\t\t\t\t\t\t'--mdfilter=enterprise.myTemplate.date<2020-01-01T00:00:00Z',\n\t\t\t\t\t],\n\t\t\t\t\t{\n\t\t\t\t\t\tmdfilters: JSON.stringify([\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tscope: 'global',\n\t\t\t\t\t\t\t\ttemplateKey: 'properties',\n\t\t\t\t\t\t\t\tfilters: {\n\t\t\t\t\t\t\t\t\tfoo: 'barf',\n\t\t\t\t\t\t\t\t\tmoney: {\n\t\t\t\t\t\t\t\t\t\tlt: 3.51,\n\t\t\t\t\t\t\t\t\t\tgt: 3.51,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\tscope: 'enterprise',\n\t\t\t\t\t\t\t\ttemplateKey: 'myTemplate',\n\t\t\t\t\t\t\t\tfilters: {\n\t\t\t\t\t\t\t\t\tbaz: 'quux',\n\t\t\t\t\t\t\t\t\tnum: {\n\t\t\t\t\t\t\t\t\t\tgt: 123,\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t\tdate: {\n\t\t\t\t\t\t\t\t\t\tlt: '2020-01-01T00:00:00Z',\n\t\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t]),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'include recent shared links flag': [\n\t\t\t\t\t['--include-recent-shared-links'],\n\t\t\t\t\t{ include_recent_shared_links: true },\n\t\t\t\t],\n\t\t\t},\n\t\t\tfunction (flags, parameters) {\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get('/2.0/search')\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\tquery,\n\t\t\t\t\t\t\tlimit: 100,\n\t\t\t\t\t\t\t...parameters,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t.get('/2.0/search')\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\tquery,\n\t\t\t\t\t\t\t...parameters,\n\t\t\t\t\t\t\tlimit: 100,\n\t\t\t\t\t\t\toffset: 5,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\t'search',\n\t\t\t\t\t\tquery,\n\t\t\t\t\t\t...flags,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should send search params when flag is passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t}\n\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/search')\n\t\t\t\t.query({\n\t\t\t\t\tquery,\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/search')\n\t\t\t\t.query({\n\t\t\t\t\tquery,\n\t\t\t\t\tlimit: 1000,\n\t\t\t\t\toffset: 5,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['search', query, '--json', '--all', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should return all results when --all flag provided',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/search')\n\t\t\t\t.query({\n\t\t\t\t\tquery,\n\t\t\t\t\tlimit: 5,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['search', query, '--json', '--limit=5', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should return limited results when --limit flag provided',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutputLimitedTo5);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/search')\n\t\t\t\t.query({\n\t\t\t\t\tquery,\n\t\t\t\t\tlimit: 5,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'search',\n\t\t\t\tquery,\n\t\t\t\t'--json',\n\t\t\t\t'--max-items=5',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should return same limited results when --max-items flag provided instead of --limit',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutputLimitedTo5);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('bulk', function () {\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/search')\n\t\t\t\t.query({\n\t\t\t\t\tlimit: 100,\n\t\t\t\t\tquery: '',\n\t\t\t\t\tscope: 'enterprise_content',\n\t\t\t\t\ttype: 'file',\n\t\t\t\t})\n\t\t\t\t.reply(200, { entries: [] })\n\t\t\t\t.get('/2.0/search')\n\t\t\t\t.query({\n\t\t\t\t\tlimit: 100,\n\t\t\t\t\tquery: '',\n\t\t\t\t\tscope: 'enterprise_content',\n\t\t\t\t\ttype: 'folder',\n\t\t\t\t})\n\t\t\t\t.reply(200, { entries: [] })\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'search',\n\t\t\t\t`--bulk-file-path=${bulkInputFilePath}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should make a successful search call for each entry in a bulk file',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedMessage = getBulkProgressBar(2);\n\t\t\t\t\texpectedMessage += `All bulk input entries processed successfully.${os.EOL}`;\n\t\t\t\t\tassert.equal(context.stderr, expectedMessage);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('fails', function () {\n\t\ttest.stderr()\n\t\t\t.command(['search', query, '--limit=80', '--all', '--token=test'])\n\t\t\t.it('when both --all and --limit flag provided', (context) => {\n\t\t\t\tassert.include(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t'--all and --limit(--max-items) flags cannot be used together.'\n\t\t\t\t);\n\t\t\t});\n\n\t\ttest.stderr()\n\t\t\t.command(['search', '--no-color', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'when query is missing and no metadata filters are provided',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Missing required argument: [QUERY]${os.EOL}` +\n\t\t\t\t\t\t\t`Usage: box search \"your search terms\"${os.EOL}` +\n\t\t\t\t\t\t\t`Example: box search \"quarterly report\" --type file${os.EOL}` +\n\t\t\t\t\t\t\t`Run: box search --help for all available filters.${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/shared-links.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst { assert } = require('chai');\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\n\ndescribe('Shared-Links', function () {\n\tdescribe('shared-links:get', function () {\n\t\tlet url = 'https://app.box.com/s/qwertyuiopasdfghjklzxcvbnm123456',\n\t\t\tfixture = getFixture('shared-links/get_shared_items'),\n\t\t\tyamlOutput = getFixture('output/shared_links_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get('/2.0/shared_items').reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['shared-links:get', url, '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information from a shared item URL (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get('/2.0/shared_items').reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['shared-links:get', url, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information from a shared item URL (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/shared_items')\n\t\t\t\t.query({ fields: 'name' })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['shared-links:get', url, '--fields=name', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('shared-links:create', function () {\n\t\tlet fileId = '1234567890',\n\t\t\tvanityName = 'my-custom-name-123',\n\t\t\tcreateFileSharedLinkFixture = getFixture(\n\t\t\t\t'files/put_files_id_shared_link'\n\t\t\t),\n\t\t\tfileJsonOutput = getFixture('output/files_share_json.txt'),\n\t\t\tfileYamlOutput = getFixture('output/files_share_yaml.txt');\n\n\t\tlet fileSharedLinkBody = {\n\t\t\tshared_link: {\n\t\t\t\tpermissions: { can_download: true, can_edit: true },\n\t\t\t\tvanity_name: vanityName,\n\t\t\t},\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(\n\t\t\t\t\t`/2.0/files/${fileId}?fields=shared_link`,\n\t\t\t\t\tfileSharedLinkBody\n\t\t\t\t)\n\t\t\t\t.reply(200, createFileSharedLinkFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'shared-links:create',\n\t\t\t\tfileId,\n\t\t\t\t'file',\n\t\t\t\t'--can-download',\n\t\t\t\t'--can-edit',\n\t\t\t\t`--vanity-name=${vanityName}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a shared link for a Box file (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fileYamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(\n\t\t\t\t\t`/2.0/files/${fileId}?fields=shared_link`,\n\t\t\t\t\tfileSharedLinkBody\n\t\t\t\t)\n\t\t\t\t.reply(200, createFileSharedLinkFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'shared-links:create',\n\t\t\t\tfileId,\n\t\t\t\t'file',\n\t\t\t\t'--can-download',\n\t\t\t\t'--can-edit',\n\t\t\t\t`--vanity-name=${vanityName}`,\n\t\t\t\t'--token=test',\n\t\t\t\t'--json',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a shared link for a Box file (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fileJsonOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\tlet folderId = '1234567890',\n\t\t\tcreateFolderSharedLinkFixture = getFixture(\n\t\t\t\t'files/put_files_id_shared_link'\n\t\t\t),\n\t\t\tfolderSharedLinkBody = {\n\t\t\t\tshared_link: {\n\t\t\t\t\tpermissions: { can_download: true },\n\t\t\t\t},\n\t\t\t};\n\n\t\tlet folderJsonOutput = getFixture('output/files_share_json.txt'),\n\t\t\tfolderYamlOutput = getFixture('output/files_share_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(\n\t\t\t\t\t`/2.0/folders/${folderId}?fields=shared_link`,\n\t\t\t\t\tfolderSharedLinkBody\n\t\t\t\t)\n\t\t\t\t.reply(200, createFolderSharedLinkFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'shared-links:create',\n\t\t\t\tfolderId,\n\t\t\t\t'folder',\n\t\t\t\t'--can-download',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a shared link for a Box folder (Yaml Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, folderYamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(\n\t\t\t\t\t`/2.0/folders/${folderId}?fields=shared_link`,\n\t\t\t\t\tfolderSharedLinkBody\n\t\t\t\t)\n\t\t\t\t.reply(200, createFolderSharedLinkFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'shared-links:create',\n\t\t\t\tfolderId,\n\t\t\t\t'folder',\n\t\t\t\t'--can-download',\n\t\t\t\t'--token=test',\n\t\t\t\t'--json',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a shared link for a Box folder (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, folderJsonOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/sign-requests.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\n\ndescribe('Sign requests', function () {\n\tdescribe('sign-requests', function () {\n\t\tconst fixture = getFixture('sign-requests/get_sign_requests');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get('/2.0/sign_requests').reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['sign-requests', '--json', '--token=test'])\n\t\t\t.it('should list sign requests', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\t});\n\n\tdescribe('sign-requests:get', function () {\n\t\tlet signRequestId = '6742981',\n\t\t\tfixture = getFixture('sign-requests/get_sign_request_by_id');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/sign_requests/${signRequestId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'sign-requests:get',\n\t\t\t\tsignRequestId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should get a sign request by id', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\t});\n\n\tdescribe('sign-requests:create', function () {\n\t\tlet signerEmail = 'bob@example.com',\n\t\t\tsignerRedirectUrl = 'https://box.com/redirect_url_signer_1',\n\t\t\tsignerDeclinedRedirectUrl =\n\t\t\t\t'https://box.com/declined_redirect_url_signer_1',\n\t\t\tfileId = '1234',\n\t\t\tfileId2 = '2345',\n\t\t\tparentFolderId = '2345',\n\t\t\tdocumentTag1Id = '3456',\n\t\t\tdocumentTag1Value = 'hello',\n\t\t\tdocumentTag2Id = '4567',\n\t\t\tfixture = getFixture('sign-requests/post_sign_requests'),\n\t\t\tredirectUrl = 'https://box.com/redirect_url',\n\t\t\tdeclinedRedirectUrl = 'https://box.com/declined_redirect_url',\n\t\t\tsignerGroupId = 'signers',\n\t\t\ttemplateId = 'c606e094-a843-4f67-9e00-542b6ce4b080';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/sign_requests', {\n\t\t\t\t\tsigners: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trole: 'approver',\n\t\t\t\t\t\t\temail: signerEmail,\n\t\t\t\t\t\t\tis_in_person: true,\n\t\t\t\t\t\t\tredirect_url: signerRedirectUrl,\n\t\t\t\t\t\t\tdeclined_redirect_url: signerDeclinedRedirectUrl,\n\t\t\t\t\t\t\tsigner_group_id: signerGroupId,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tsource_files: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'file',\n\t\t\t\t\t\t\tid: fileId,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'file',\n\t\t\t\t\t\t\tid: fileId2,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tparent_folder: {\n\t\t\t\t\t\ttype: 'folder',\n\t\t\t\t\t\tid: parentFolderId,\n\t\t\t\t\t},\n\t\t\t\t\tprefill_tags: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdocument_tag_id: documentTag1Id,\n\t\t\t\t\t\t\ttext_value: documentTag1Value,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdocument_tag_id: documentTag2Id,\n\t\t\t\t\t\t\tcheckbox_value: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tredirect_url: redirectUrl,\n\t\t\t\t\tdeclined_redirect_url: declinedRedirectUrl,\n\t\t\t\t\ttemplate_id: templateId,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'sign-requests:create',\n\t\t\t\t`--signer=email=${signerEmail},role=approver,is_in_person=1,redirect_url=${signerRedirectUrl},declined_redirect_url=${signerDeclinedRedirectUrl},group_id=${signerGroupId}`,\n\t\t\t\t`--source-files=${fileId},${fileId2}`,\n\t\t\t\t`--parent-folder=${parentFolderId}`,\n\t\t\t\t`--prefill-tag=id=${documentTag1Id},text=${documentTag1Value}`,\n\t\t\t\t`--prefill-tag=id=${documentTag2Id},checkbox=0`,\n\t\t\t\t`--redirect-url=${redirectUrl}`,\n\t\t\t\t`--declined-redirect-url=${declinedRedirectUrl}`,\n\t\t\t\t`--template-id=${templateId}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should create a sign request with snake case', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/sign_requests', {\n\t\t\t\t\tsigners: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\trole: 'approver',\n\t\t\t\t\t\t\temail: signerEmail,\n\t\t\t\t\t\t\tis_in_person: true,\n\t\t\t\t\t\t\tredirect_url: signerRedirectUrl,\n\t\t\t\t\t\t\tdeclined_redirect_url: signerDeclinedRedirectUrl,\n\t\t\t\t\t\t\tsigner_group_id: signerGroupId,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tsource_files: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'file',\n\t\t\t\t\t\t\tid: fileId,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\ttype: 'file',\n\t\t\t\t\t\t\tid: fileId2,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tparent_folder: {\n\t\t\t\t\t\ttype: 'folder',\n\t\t\t\t\t\tid: parentFolderId,\n\t\t\t\t\t},\n\t\t\t\t\tprefill_tags: [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdocument_tag_id: documentTag1Id,\n\t\t\t\t\t\t\ttext_value: documentTag1Value,\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tdocument_tag_id: documentTag2Id,\n\t\t\t\t\t\t\tcheckbox_value: false,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t\tredirect_url: redirectUrl,\n\t\t\t\t\tdeclined_redirect_url: declinedRedirectUrl,\n\t\t\t\t\ttemplate_id: templateId,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'sign-requests:create',\n\t\t\t\t`--signer=email=${signerEmail},role=approver,is-in-person=1,redirect-url=${signerRedirectUrl},declined-redirect-url=${signerDeclinedRedirectUrl},group-id=${signerGroupId}`,\n\t\t\t\t`--source-files=${fileId},${fileId2}`,\n\t\t\t\t`--parent-folder=${parentFolderId}`,\n\t\t\t\t`--prefill-tag=id=${documentTag1Id},text=${documentTag1Value}`,\n\t\t\t\t`--prefill-tag=id=${documentTag2Id},checkbox=0`,\n\t\t\t\t`--redirect-url=${redirectUrl}`,\n\t\t\t\t`--declined-redirect-url=${declinedRedirectUrl}`,\n\t\t\t\t`--template-id=${templateId}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should create a sign request with kebab case', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\t});\n\n\tdescribe('sign-requests:cancel', function () {\n\t\tlet signRequestId = '6742981',\n\t\t\tfixture = getFixture('sign-requests/post_sign_requests_id_cancel');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/sign_requests/${signRequestId}/cancel`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'sign-requests:cancel',\n\t\t\t\tsignRequestId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should cancel a sign request by id', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\t});\n\n\tdescribe('sign-requests:resend', function () {\n\t\tlet signRequestId = '6742981';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post(`/2.0/sign_requests/${signRequestId}/resend`).reply(200)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'sign-requests:resend',\n\t\t\t\tsignRequestId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should resend a sign request by id', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Resent sign request ${signRequestId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/commands/sign-templates.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\n\ndescribe('Sign templates', function () {\n\tdescribe('sign-templates', function () {\n\t\tconst fixture = getFixture('sign-templates/get_sign_templates');\n\t\tconst jsonOutput = getFixture('output/sign_templates_json.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get('/2.0/sign_templates').reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['sign-templates', '--json', '--token=test'])\n\t\t\t.it('should list sign templates', (context) => {\n\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t});\n\t});\n\n\tdescribe('sign-templates:get', function () {\n\t\tlet signTemplateId = '6742981',\n\t\t\tfixture = getFixture('sign-templates/get_sign_template_by_id');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/sign_templates/${signTemplateId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'sign-templates:get',\n\t\t\t\tsignTemplateId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should get a sign template by id', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/commands/storage-policies.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\nconst leche = require('leche');\n\ndescribe('Storage-policies', function () {\n\tdescribe('storage-policies:get', function () {\n\t\tlet storagePolicyId = '123',\n\t\t\tfixture = getFixture('storage-policies/get_storage_policies_id'),\n\t\t\tyamlOutput = getFixture('output/storage_policies_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/storage_policies/${storagePolicyId}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'storage-policies:get',\n\t\t\t\tstoragePolicyId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information on a storage policy (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/storage_policies/${storagePolicyId}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['storage-policies:get', storagePolicyId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information on a storage policy (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tleche.withData(\n\t\t['storage-policies', 'storage-policies:list'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet fixture = getFixture(\n\t\t\t\t\t\t'storage-policies/get_storage_policies_page_1'\n\t\t\t\t\t),\n\t\t\t\t\tfixture2 = getFixture(\n\t\t\t\t\t\t'storage-policies/get_storage_policies_page_2'\n\t\t\t\t\t),\n\t\t\t\t\tjsonOutput = getFixture(\n\t\t\t\t\t\t'output/storage_policies_list_json.txt'\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get('/2.0/storage_policies')\n\t\t\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t.get('/2.0/storage_policies')\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\tmarker: 'ZDE789',\n\t\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, '--json', '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should list storage policies (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tdescribe('storage-policies:assignments:get', function () {\n\t\tlet assignmentId = 'user_987654321',\n\t\t\tfixture = getFixture(\n\t\t\t\t'storage-policies/get_storage_policy_assignments_id'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/storage_policies_get_assignment_yaml.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/storage_policy_assignments/${assignmentId}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'storage-policies:assignments:get',\n\t\t\t\tassignmentId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information on a storage policy assignment (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/storage_policy_assignments/${assignmentId}`)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'storage-policies:assignments:get',\n\t\t\t\tassignmentId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information on a storage policy assignment (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('storage-policies:assignments:lookup', function () {\n\t\tlet enterpriseId = '77777',\n\t\t\ttype = 'enterprise',\n\t\t\tfixture = getFixture(\n\t\t\t\t'storage-policies/get_storage_policy_assignments_resolved_for_enterprise'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/storage_policies_lookup_assignment_yaml.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/storage_policy_assignments')\n\t\t\t\t.query({\n\t\t\t\t\tresolved_for_type: type,\n\t\t\t\t\tresolved_for_id: enterpriseId,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'storage-policies:assignments:lookup',\n\t\t\t\t`--type=${type}`,\n\t\t\t\tenterpriseId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should look up which storage policy an object is assigned to (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedObject = JSON.parse(fixture).entries[0];\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.stringify(expectedObject, null, 4)}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/storage_policy_assignments')\n\t\t\t\t.query({\n\t\t\t\t\tresolved_for_type: type,\n\t\t\t\t\tresolved_for_id: enterpriseId,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'storage-policies:assignments:lookup',\n\t\t\t\tenterpriseId,\n\t\t\t\t`--type=${type}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should look up which storage policy an object is assigned to (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('storage-policies:assign', function () {\n\t\tlet policyId = '223',\n\t\t\tuserId = '987654321',\n\t\t\tfixture = getFixture(\n\t\t\t\t'storage-policies/post_storage_policy_assignments'\n\t\t\t),\n\t\t\tenterpriseAssignmentFixture = getFixture(\n\t\t\t\t'storage-policies/get_storage_policy_assignments_resolved_for_enterprise'\n\t\t\t),\n\t\t\tyamlOutput = getFixture('output/storage_policies_assign_yaml.txt');\n\n\t\tlet expectedBody = {\n\t\t\tstorage_policy: {\n\t\t\t\ttype: 'storage_policy',\n\t\t\t\tid: policyId,\n\t\t\t},\n\t\t\tassigned_to: {\n\t\t\t\ttype: 'user',\n\t\t\t\tid: userId,\n\t\t\t},\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/storage_policy_assignments')\n\t\t\t\t.query({\n\t\t\t\t\tresolved_for_id: userId,\n\t\t\t\t\tresolved_for_type: 'user',\n\t\t\t\t})\n\t\t\t\t.reply(200, enterpriseAssignmentFixture)\n\t\t\t\t.post('/2.0/storage_policy_assignments', expectedBody)\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'storage-policies:assign',\n\t\t\t\tpolicyId,\n\t\t\t\tuserId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should assign a storage policy (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/storage_policy_assignments')\n\t\t\t\t.query({\n\t\t\t\t\tresolved_for_id: userId,\n\t\t\t\t\tresolved_for_type: 'user',\n\t\t\t\t})\n\t\t\t\t.reply(200, enterpriseAssignmentFixture)\n\t\t\t\t.post('/2.0/storage_policy_assignments', expectedBody)\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'storage-policies:assign',\n\t\t\t\tpolicyId,\n\t\t\t\tuserId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should assign a storage policy (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\t});\n\n\tdescribe('storage-policies:assignments:remove', function () {\n\t\tlet assignmentId = 'user_987654321';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(`/2.0/storage_policy_assignments/${assignmentId}`)\n\t\t\t\t.reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command([\n\t\t\t\t'storage-policies:assignments:remove',\n\t\t\t\tassignmentId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should delete storage policy assignment', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Deleted storage policy assignment ${assignmentId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/commands/tasks.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\nconst leche = require('leche');\n\ndescribe('Tasks', function () {\n\tdescribe('tasks:create', function () {\n\t\tlet type = 'file',\n\t\t\tid = '22222',\n\t\t\tmessage = 'Please review',\n\t\t\tdueDate = '2019-01-01T09:00:00+00:00',\n\t\t\tcompletionRule = 'any_assignee',\n\t\t\tfixture = getFixture('tasks/post_tasks'),\n\t\t\tyamlOutput = getFixture('output/tasks_create_yaml.txt');\n\n\t\tlet expectedBody = {\n\t\t\tmessage,\n\t\t\taction: 'review',\n\t\t\titem: { type, id },\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/tasks', expectedBody).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'tasks:create',\n\t\t\t\tid,\n\t\t\t\t`--message=${message}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a task on a file with the message flag passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/tasks', expectedBody).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'tasks:create',\n\t\t\t\tid,\n\t\t\t\t`--message=${message}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a task on a file with the message flag passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/tasks', expectedBody).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'tasks:create',\n\t\t\t\tid,\n\t\t\t\t`--message=${message}`,\n\t\t\t\t'--id-only',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a task on a file with the message flag passed (ID Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.parse(fixture).id}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/tasks', {\n\t\t\t\t\titem: { type, id },\n\t\t\t\t\taction: 'review',\n\t\t\t\t\tdue_at: dueDate,\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'tasks:create',\n\t\t\t\tid,\n\t\t\t\t`--due-at=${dueDate}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create task with a due date when the --due-at flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/tasks', {\n\t\t\t\t\titem: { type, id },\n\t\t\t\t\taction: 'review',\n\t\t\t\t\tcompletion_rule: completionRule,\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'tasks:create',\n\t\t\t\tid,\n\t\t\t\t`--completion-rule=${completionRule}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create task with a completion rule when --completion-rule flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('tasks:update', function () {\n\t\tlet taskId = '11111',\n\t\t\tmessage = 'Could you please review this?',\n\t\t\tdueDate = '2019-01-01T09:00:00+00:00',\n\t\t\tcompletionRule = 'any_assignee',\n\t\t\tfixture = getFixture('tasks/put_tasks_id'),\n\t\t\tyamlOutput = getFixture('output/tasks_update_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.put(`/2.0/tasks/${taskId}`, { message }).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'tasks:update',\n\t\t\t\ttaskId,\n\t\t\t\t`--message=${message}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a task on a file with the message flag passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.put(`/2.0/tasks/${taskId}`, { message }).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'tasks:update',\n\t\t\t\ttaskId,\n\t\t\t\t`--message=${message}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a task on a file with the message flag passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/tasks/${taskId}`, { due_at: dueDate })\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'tasks:update',\n\t\t\t\ttaskId,\n\t\t\t\t`--due-at=${dueDate}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update task due date when the --due-at flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/tasks/${taskId}`, {\n\t\t\t\t\tcompletion_rule: completionRule,\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'tasks:update',\n\t\t\t\ttaskId,\n\t\t\t\t`--completion-rule=${completionRule}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update task with a completion rule when --completion-rule flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('tasks:get', function () {\n\t\tlet taskId = '11111',\n\t\t\tfixture = getFixture('tasks/put_tasks_id'),\n\t\t\tyamlOutput = getFixture('output/tasks_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/tasks/${taskId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['tasks:get', taskId, '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a task (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/tasks/${taskId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['tasks:get', taskId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a task (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/tasks/${taskId}`)\n\t\t\t\t.query({ fields: 'action' })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['tasks:get', taskId, '--fields=action', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tdescribe('tasks:delete', function () {\n\t\tlet taskId = '11111';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.delete(`/2.0/tasks/${taskId}`).reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['tasks:delete', taskId, '--token=test'])\n\t\t\t.it('should delete a task', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Successfully deleted task ${taskId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tleche.withData(\n\t\t['tasks:assign', 'task-assignments:create'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet taskId = '11111',\n\t\t\t\t\tuserId = '33333',\n\t\t\t\t\tuserLogin = 'foo@example.com',\n\t\t\t\t\tfixture = getFixture(\n\t\t\t\t\t\t'task-assignments/post_task_assignments'\n\t\t\t\t\t),\n\t\t\t\t\tyamlOutput = getFixture(\n\t\t\t\t\t\t'output/task_assignments_create_yaml.txt'\n\t\t\t\t\t);\n\n\t\t\t\tlet expectedBody = {\n\t\t\t\t\ttask: {\n\t\t\t\t\t\ttype: 'task',\n\t\t\t\t\t\tid: taskId,\n\t\t\t\t\t},\n\t\t\t\t\tassign_to: {\n\t\t\t\t\t\tid: userId,\n\t\t\t\t\t},\n\t\t\t\t};\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post('/2.0/task_assignments', expectedBody)\n\t\t\t\t\t\t.reply(201, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\ttaskId,\n\t\t\t\t\t\t`--assign-to-user-id=${userId}`,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should create a task assignment with the assign-to-user-id passed (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post('/2.0/task_assignments', expectedBody)\n\t\t\t\t\t\t.reply(201, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\ttaskId,\n\t\t\t\t\t\t`--assign-to-user-id=${userId}`,\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should create a task assignment with the assign-to-user-id passed (YAML Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post('/2.0/task_assignments', {\n\t\t\t\t\t\t\t...expectedBody,\n\t\t\t\t\t\t\tassign_to: {\n\t\t\t\t\t\t\t\tlogin: userLogin,\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(201, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\ttaskId,\n\t\t\t\t\t\t`--assign-to-user-login=${userLogin}`,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should create a task assignment with the assign-to-user-login flag',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tleche.withData(\n\t\t['tasks:assignments:delete', 'task-assignments:delete'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet assignmentId = '12345';\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.delete(`/2.0/task_assignments/${assignmentId}`)\n\t\t\t\t\t\t.reply(204)\n\t\t\t\t)\n\t\t\t\t\t.stderr()\n\t\t\t\t\t.command([command, assignmentId, '--token=test'])\n\t\t\t\t\t.it('should delete a task assignment', (context) => {\n\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t\t`Successfully deleted task assignment ${assignmentId}${os.EOL}`\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t});\n\t\t}\n\t);\n\n\tleche.withData(\n\t\t['tasks:assignments:get', 'task-assignments:get'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet assignmentId = '12345',\n\t\t\t\t\tfixture = getFixture(\n\t\t\t\t\t\t'task-assignments/post_task_assignments'\n\t\t\t\t\t),\n\t\t\t\t\tyamlOutput = getFixture(\n\t\t\t\t\t\t'output/task_assignments_get_yaml.txt'\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/task_assignments/${assignmentId}`)\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, assignmentId, '--json', '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should get information about a task assignment (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/task_assignments/${assignmentId}`)\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, assignmentId, '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should get information about a task assignment (YAML Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/task_assignments/${assignmentId}`)\n\t\t\t\t\t\t.query({ fields: 'id' })\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tassignmentId,\n\t\t\t\t\t\t'--fields=id',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tleche.withData(\n\t\t['tasks:assignments', 'task-assignments:list'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet taskId = '11111',\n\t\t\t\t\tfixture = getFixture(\n\t\t\t\t\t\t'task-assignments/get_tasks_id_assignments'\n\t\t\t\t\t),\n\t\t\t\t\tjsonOutput = getFixture(\n\t\t\t\t\t\t'output/task_assignments_list_json.txt'\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/tasks/${taskId}/assignments`)\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, taskId, '--json', '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should list all task assignments on a task',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/tasks/${taskId}/assignments`)\n\t\t\t\t\t\t.query({ fields: 'id' })\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\ttaskId,\n\t\t\t\t\t\t'--fields=id',\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tleche.withData(\n\t\t['tasks:assignments:update', 'task-assignments:update'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet assignmentId = '12345',\n\t\t\t\t\tmessage = 'Looks good to me!',\n\t\t\t\t\tfixture = getFixture(\n\t\t\t\t\t\t'task-assignments/put_task_assignments_id'\n\t\t\t\t\t),\n\t\t\t\t\tyamlOutput = getFixture(\n\t\t\t\t\t\t'output/task_assignments_update_yaml.txt'\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(`/2.0/task_assignments/${assignmentId}`, {\n\t\t\t\t\t\t\tmessage,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tassignmentId,\n\t\t\t\t\t\t`--message=${message}`,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should update a task assignment with message flag passed (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(`/2.0/task_assignments/${assignmentId}`, {\n\t\t\t\t\t\t\tmessage,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tassignmentId,\n\t\t\t\t\t\t`--message=${message}`,\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should update a task assignment with message flag passed (YAML Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\tleche.withData(\n\t\t\t\t\t{\n\t\t\t\t\t\t'completed flag': ['--completed', 'completed'],\n\t\t\t\t\t\t'incomplete flag': ['--incomplete', 'incomplete'],\n\t\t\t\t\t\t'approved flag': ['--approved', 'approved'],\n\t\t\t\t\t\t'rejected flag': ['--rejected', 'rejected'],\n\t\t\t\t\t\t'status flag set to completed': [\n\t\t\t\t\t\t\t'--status=completed',\n\t\t\t\t\t\t\t'completed',\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'status flag set to incomplete': [\n\t\t\t\t\t\t\t'--status=incomplete',\n\t\t\t\t\t\t\t'incomplete',\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'status flag set to approved': [\n\t\t\t\t\t\t\t'--status=approved',\n\t\t\t\t\t\t\t'approved',\n\t\t\t\t\t\t],\n\t\t\t\t\t\t'status flag set to rejected': [\n\t\t\t\t\t\t\t'--status=rejected',\n\t\t\t\t\t\t\t'rejected',\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t\tfunction (flag, resolutionState) {\n\t\t\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\t\t\tapi\n\t\t\t\t\t\t\t\t.put(`/2.0/task_assignments/${assignmentId}`, {\n\t\t\t\t\t\t\t\t\tresolution_state: resolutionState,\n\t\t\t\t\t\t\t\t})\n\t\t\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t)\n\t\t\t\t\t\t\t.stdout()\n\t\t\t\t\t\t\t.command([\n\t\t\t\t\t\t\t\tcommand,\n\t\t\t\t\t\t\t\tassignmentId,\n\t\t\t\t\t\t\t\tflag,\n\t\t\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t\t\t])\n\t\t\t\t\t\t\t.it(\n\t\t\t\t\t\t\t\t'should update a task assignment with resolution state flag passed',\n\t\t\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n});\n"
  },
  {
    "path": "test/commands/terms-of-service.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst { assert } = require('chai');\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\n\ndescribe('Terms of Service', function () {\n\tdescribe('terms-of-service:get', function () {\n\t\tlet tosId = '12345',\n\t\t\tfixture = getFixture('terms-of-service/get_terms_of_service_id'),\n\t\t\tyamlOutput = getFixture('output/terms_of_service_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/terms_of_services/${tosId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['terms-of-service:get', tosId, '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information on a terms of service (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/terms_of_services/${tosId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['terms-of-service:get', tosId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information on a terms of service (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('terms-of-service', function () {\n\t\tlet tosType = 'managed',\n\t\t\tfixture = getFixture('terms-of-service/get_terms_of_services'),\n\t\t\tjsonOutput = getFixture('output/terms_of_service_list_json.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/terms_of_services')\n\t\t\t\t.query({\n\t\t\t\t\ttos_type: tosType,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'terms-of-service',\n\t\t\t\t`--type=${tosType}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should list terms of services for your enterprise with the type flag passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('terms-of-service:create', function () {\n\t\tlet tosType = 'managed',\n\t\t\tstatus = 'enabled',\n\t\t\ttext = 'test',\n\t\t\tfixture = getFixture('terms-of-service/post_terms_of_service_id'),\n\t\t\tyamlOutput = getFixture('output/terms_of_service_create_yaml.txt');\n\n\t\tlet expectedBody = {\n\t\t\ttos_type: tosType,\n\t\t\tstatus,\n\t\t\ttext,\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/terms_of_services', expectedBody).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'terms-of-service:create',\n\t\t\t\t`--type=${tosType}`,\n\t\t\t\t`--status=${status}`,\n\t\t\t\t`--text=${text}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should create a terms of service (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/terms_of_services').reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'terms-of-service:create',\n\t\t\t\t`--type=${tosType}`,\n\t\t\t\t`--status=${status}`,\n\t\t\t\t`--text=${text}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should create a terms of service (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\t});\n\n\tdescribe('terms-of-service:update', function () {\n\t\tlet tosId = '12345',\n\t\t\tstatus = 'enabled',\n\t\t\ttext = 'test',\n\t\t\tfixture = getFixture('terms-of-service/put_terms_of_service_id'),\n\t\t\tyamlOutput = getFixture('output/terms_of_service_update_yaml.txt');\n\n\t\tlet expectedBody = {\n\t\t\tstatus,\n\t\t\ttext,\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/terms_of_services/${tosId}`, expectedBody)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'terms-of-service:update',\n\t\t\t\ttosId,\n\t\t\t\t`--status=${status}`,\n\t\t\t\t`--text=${text}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should update a terms of service (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/terms_of_services/${tosId}`, expectedBody)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'terms-of-service:update',\n\t\t\t\ttosId,\n\t\t\t\t`--status=${status}`,\n\t\t\t\t`--text=${text}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should update a terms of service (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\t});\n\n\tdescribe('terms-of-service:get-user-status', function () {\n\t\tlet tosId = '1234',\n\t\t\tuserId = '7777',\n\t\t\tfixture = getFixture(\n\t\t\t\t'terms-of-service/get_terms_of_service_user_statuses'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/terms_of_service_get_user_status_yaml.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/terms_of_service_user_statuses')\n\t\t\t\t.query({\n\t\t\t\t\ttos_id: tosId,\n\t\t\t\t\tuser_id: userId,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'terms-of-service:get-user-status',\n\t\t\t\ttosId,\n\t\t\t\t`--user-id=${userId}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t\"should get a user's status on a terms of service (JSON Output)\",\n\t\t\t\t(context) => {\n\t\t\t\t\tlet expectedObject = JSON.parse(fixture).entries[0];\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.stringify(expectedObject, null, 4)}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/terms_of_service_user_statuses')\n\t\t\t\t.query({\n\t\t\t\t\ttos_id: tosId,\n\t\t\t\t\tuser_id: userId,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'terms-of-service:get-user-status',\n\t\t\t\ttosId,\n\t\t\t\t`--user-id=${userId}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t\"should get a user's status on a terms of service (YAML Output)\",\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('terms-of-service:set-user-status', function () {\n\t\tlet tosId = '1234',\n\t\t\tuserId = '7777',\n\t\t\tpostResponse = getFixture(\n\t\t\t\t'terms-of-service/post_terms_of_service_user_statuses_409'\n\t\t\t),\n\t\t\tgetResponse = getFixture(\n\t\t\t\t'terms-of-service/get_terms_of_service_user_statuses'\n\t\t\t),\n\t\t\tputResponse = getFixture(\n\t\t\t\t'terms-of-service/put_terms_of_service_user_statuses'\n\t\t\t),\n\t\t\tyamlOutput = getFixture(\n\t\t\t\t'output/terms_of_service_set_user_status_yaml.txt'\n\t\t\t),\n\t\t\ttosUserStatusId = JSON.parse(getResponse).entries[0].id;\n\n\t\tlet user = {\n\t\t\tid: userId,\n\t\t\ttype: 'user',\n\t\t};\n\n\t\tlet expectedPostBody = {\n\t\t\ttos: {\n\t\t\t\tid: tosId,\n\t\t\t\ttype: 'terms_of_service',\n\t\t\t},\n\t\t\tuser,\n\t\t\tis_accepted: true,\n\t\t};\n\n\t\tlet expectedPutBody = {\n\t\t\tis_accepted: true,\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/terms_of_service_user_statuses', expectedPostBody)\n\t\t\t\t.reply(409, postResponse)\n\t\t\t\t.get('/2.0/terms_of_service_user_statuses')\n\t\t\t\t.query({\n\t\t\t\t\ttos_id: tosId,\n\t\t\t\t\tuser_id: userId,\n\t\t\t\t\tfields: 'id',\n\t\t\t\t})\n\t\t\t\t.reply(200, getResponse)\n\t\t\t\t.put(\n\t\t\t\t\t`/2.0/terms_of_service_user_statuses/${tosUserStatusId}`,\n\t\t\t\t\texpectedPutBody\n\t\t\t\t)\n\t\t\t\t.reply(200, putResponse)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'terms-of-service:set-user-status',\n\t\t\t\ttosId,\n\t\t\t\t`--user-id=${userId}`,\n\t\t\t\t'--accept',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t\"should set a user's status on a terms of service with a terms of service Id with the accept flag passed (JSON Output)\",\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, putResponse);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/terms_of_service_user_statuses', expectedPostBody)\n\t\t\t\t.reply(409, postResponse)\n\t\t\t\t.get('/2.0/terms_of_service_user_statuses')\n\t\t\t\t.query({\n\t\t\t\t\ttos_id: tosId,\n\t\t\t\t\tuser_id: userId,\n\t\t\t\t\tfields: 'id',\n\t\t\t\t})\n\t\t\t\t.reply(200, getResponse)\n\t\t\t\t.put(\n\t\t\t\t\t`/2.0/terms_of_service_user_statuses/${tosUserStatusId}`,\n\t\t\t\t\texpectedPutBody\n\t\t\t\t)\n\t\t\t\t.reply(200, putResponse)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'terms-of-service:set-user-status',\n\t\t\t\ttosId,\n\t\t\t\t`--user-id=${userId}`,\n\t\t\t\t'--accept',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t\"should set a user's status on a terms of service with a terms of service Id with the accept flag passed (JSON Output)\",\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/tokens.test.js",
    "content": "'use strict';\n\n/* eslint-disable mocha/no-skipped-tests */\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst jwt = require('jsonwebtoken');\nconst { TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\n\ndescribe('Tokens', function () {\n\tconst TEST_ACCESS_TOKEN = 'alksudiquwdajnsfisdfgsdfg';\n\n\t// @TODO(2018-12-13): Un-skip when tests can have a config set up\n\tdescribe.skip('tokens:get', function () {\n\t\tconst userID = '98764';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/oauth2/token', (body) => {\n\t\t\t\t\tassert.propertyVal(\n\t\t\t\t\t\tbody,\n\t\t\t\t\t\t'grant_type',\n\t\t\t\t\t\t'urn:ietf:params:oauth:grant-type:jwt-bearer'\n\t\t\t\t\t);\n\t\t\t\t\tassert.property(body, 'assertion');\n\n\t\t\t\t\tlet parsedJWT = jwt.decode(body.assertion, {\n\t\t\t\t\t\tcomplete: true,\n\t\t\t\t\t});\n\t\t\t\t\tassert.nestedPropertyVal(\n\t\t\t\t\t\tparsedJWT,\n\t\t\t\t\t\t'payload.box_sub_type',\n\t\t\t\t\t\t'enterprise'\n\t\t\t\t\t);\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.reply(200, {\n\t\t\t\t\taccess_token: TEST_ACCESS_TOKEN,\n\t\t\t\t\texpires_in: 256,\n\t\t\t\t})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['tokens:get'])\n\t\t\t.it(\n\t\t\t\t'should output token for service account when called without flags',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${TEST_ACCESS_TOKEN}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/oauth2/token', (body) => {\n\t\t\t\t\tassert.propertyVal(\n\t\t\t\t\t\tbody,\n\t\t\t\t\t\t'grant_type',\n\t\t\t\t\t\t'urn:ietf:params:oauth:grant-type:jwt-bearer'\n\t\t\t\t\t);\n\t\t\t\t\tassert.property(body, 'assertion');\n\n\t\t\t\t\tlet parsedJWT = jwt.decode(body.assertion, {\n\t\t\t\t\t\tcomplete: true,\n\t\t\t\t\t});\n\t\t\t\t\tassert.nestedPropertyVal(\n\t\t\t\t\t\tparsedJWT,\n\t\t\t\t\t\t'payload.box_sub_type',\n\t\t\t\t\t\t'user'\n\t\t\t\t\t);\n\t\t\t\t\tassert.nestedPropertyVal(parsedJWT, 'payload.sub', userID);\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.reply(200, {\n\t\t\t\t\taccess_token: TEST_ACCESS_TOKEN,\n\t\t\t\t\texpires_in: 256,\n\t\t\t\t})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['tokens:get', `--user-id=${userID}`])\n\t\t\t.it(\n\t\t\t\t'should output token for user when called with --user-id flag',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${TEST_ACCESS_TOKEN}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\t// @TODO(2018-12-13): Un-skip when tests can have a config set up\n\tdescribe.skip('tokens:revoke', function () {\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/oauth2/revoke', (body) => {\n\t\t\t\t\tassert.propertyVal(body, 'token', TEST_ACCESS_TOKEN);\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.reply(200)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command(['tokens:revoke', TEST_ACCESS_TOKEN])\n\t\t\t.it('should revoke token when called', (context) => {\n\t\t\t\tassert.equal(context.stderr, `Token revoked.${os.EOL}`);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/oauth2/revoke', (body) => {\n\t\t\t\t\tassert.propertyVal(body, 'token', TEST_ACCESS_TOKEN);\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.reply(400, {\n\t\t\t\t\terror: 'invalid_token',\n\t\t\t\t\terror_description: 'The supplied token is invalid',\n\t\t\t\t})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.stderr()\n\t\t\t.command(['tokens:revoke', TEST_ACCESS_TOKEN])\n\t\t\t.it(\n\t\t\t\t'should output error message when token revocation fails',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Error revoking token!  The supplied token is invalid${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\t// @TODO(2018-12-13): Un-skip when tests can have a config set up\n\tdescribe.skip('tokens:exchange', function () {\n\t\tlet scopes = ['item_preview', 'user_view'];\n\n\t\tconst itemID = '12345';\n\t\tconst userID = '87645';\n\t\tconst downscopedToken = 'ppuipoierhkjbdkjbsdfg';\n\n\t\tlet expectedBody = {\n\t\t\tsubject_token: TEST_ACCESS_TOKEN,\n\t\t\tsubject_token_type: 'urn:ietf:params:oauth:token-type:access_token',\n\t\t\tscope: scopes.join(' '),\n\t\t\tgrant_type: 'urn:ietf:params:oauth:grant-type:token-exchange',\n\t\t};\n\n\t\ttest.skip()\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.post('/oauth2/token', (body) => {\n\t\t\t\t\t\tassert.propertyVal(\n\t\t\t\t\t\t\tbody,\n\t\t\t\t\t\t\t'grant_type',\n\t\t\t\t\t\t\t'urn:ietf:params:oauth:grant-type:jwt-bearer'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.property(body, 'assertion');\n\n\t\t\t\t\t\tlet parsedJWT = jwt.decode(body.assertion, {\n\t\t\t\t\t\t\tcomplete: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tassert.nestedPropertyVal(\n\t\t\t\t\t\t\tparsedJWT,\n\t\t\t\t\t\t\t'payload.box_sub_type',\n\t\t\t\t\t\t\t'enterprise'\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, {\n\t\t\t\t\t\taccess_token: TEST_ACCESS_TOKEN,\n\t\t\t\t\t\texpires_in: 256,\n\t\t\t\t\t})\n\t\t\t\t\t.post('/oauth2/token', (body) => {\n\t\t\t\t\t\tassert.include(body, expectedBody);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, {\n\t\t\t\t\t\taccess_token: downscopedToken,\n\t\t\t\t\t\texpires_in: 256,\n\t\t\t\t\t})\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['tokens:exchange', scopes.join(',')])\n\t\t\t.it('should exchange token for one with lower scope', (context) => {\n\t\t\t\tassert.equal(context.stdout, `${downscopedToken}${os.EOL}`);\n\t\t\t});\n\n\t\ttest.skip()\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.post('/oauth2/token', (body) => {\n\t\t\t\t\t\tassert.propertyVal(\n\t\t\t\t\t\t\tbody,\n\t\t\t\t\t\t\t'grant_type',\n\t\t\t\t\t\t\t'urn:ietf:params:oauth:grant-type:jwt-bearer'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.property(body, 'assertion');\n\n\t\t\t\t\t\tlet parsedJWT = jwt.decode(body.assertion, {\n\t\t\t\t\t\t\tcomplete: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tassert.nestedPropertyVal(\n\t\t\t\t\t\t\tparsedJWT,\n\t\t\t\t\t\t\t'payload.box_sub_type',\n\t\t\t\t\t\t\t'enterprise'\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, {\n\t\t\t\t\t\taccess_token: TEST_ACCESS_TOKEN,\n\t\t\t\t\t\texpires_in: 256,\n\t\t\t\t\t})\n\t\t\t\t\t.post('/oauth2/token', (body) => {\n\t\t\t\t\t\tassert.include(body, expectedBody);\n\t\t\t\t\t\tassert.propertyVal(\n\t\t\t\t\t\t\tbody,\n\t\t\t\t\t\t\t'resource',\n\t\t\t\t\t\t\t`https://api.box.com/2.0/files/${itemID}`\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, {\n\t\t\t\t\t\taccess_token: downscopedToken,\n\t\t\t\t\t\texpires_in: 256,\n\t\t\t\t\t})\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'tokens:exchange',\n\t\t\t\tscopes.join(','),\n\t\t\t\t`--file-id=${itemID}`,\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should restrict downscoped token to file resource when passed file ID',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, `${downscopedToken}${os.EOL}`);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.skip()\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.post('/oauth2/token', (body) => {\n\t\t\t\t\t\tassert.propertyVal(\n\t\t\t\t\t\t\tbody,\n\t\t\t\t\t\t\t'grant_type',\n\t\t\t\t\t\t\t'urn:ietf:params:oauth:grant-type:jwt-bearer'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.property(body, 'assertion');\n\n\t\t\t\t\t\tlet parsedJWT = jwt.decode(body.assertion, {\n\t\t\t\t\t\t\tcomplete: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tassert.nestedPropertyVal(\n\t\t\t\t\t\t\tparsedJWT,\n\t\t\t\t\t\t\t'payload.box_sub_type',\n\t\t\t\t\t\t\t'enterprise'\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, {\n\t\t\t\t\t\taccess_token: TEST_ACCESS_TOKEN,\n\t\t\t\t\t\texpires_in: 256,\n\t\t\t\t\t})\n\t\t\t\t\t.post('/oauth2/token', (body) => {\n\t\t\t\t\t\tassert.include(body, expectedBody);\n\t\t\t\t\t\tassert.propertyVal(\n\t\t\t\t\t\t\tbody,\n\t\t\t\t\t\t\t'resource',\n\t\t\t\t\t\t\t`https://api.box.com/2.0/folders/${itemID}`\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, {\n\t\t\t\t\t\taccess_token: downscopedToken,\n\t\t\t\t\t\texpires_in: 256,\n\t\t\t\t\t})\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'tokens:exchange',\n\t\t\t\tscopes.join(','),\n\t\t\t\t`--folder-id=${itemID}`,\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should restrict downscoped token to folder resource when passed folder ID',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, `${downscopedToken}${os.EOL}`);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.skip()\n\t\t\t.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.post('/oauth2/token', (body) => {\n\t\t\t\t\t\tassert.propertyVal(\n\t\t\t\t\t\t\tbody,\n\t\t\t\t\t\t\t'grant_type',\n\t\t\t\t\t\t\t'urn:ietf:params:oauth:grant-type:jwt-bearer'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.property(body, 'assertion');\n\n\t\t\t\t\t\tlet parsedJWT = jwt.decode(body.assertion, {\n\t\t\t\t\t\t\tcomplete: true,\n\t\t\t\t\t\t});\n\t\t\t\t\t\tassert.nestedPropertyVal(\n\t\t\t\t\t\t\tparsedJWT,\n\t\t\t\t\t\t\t'payload.box_sub_type',\n\t\t\t\t\t\t\t'user'\n\t\t\t\t\t\t);\n\t\t\t\t\t\tassert.nestedPropertyVal(\n\t\t\t\t\t\t\tparsedJWT,\n\t\t\t\t\t\t\t'payload.sub',\n\t\t\t\t\t\t\tuserID\n\t\t\t\t\t\t);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, {\n\t\t\t\t\t\taccess_token: TEST_ACCESS_TOKEN,\n\t\t\t\t\t\texpires_in: 256,\n\t\t\t\t\t})\n\t\t\t\t\t.post('/oauth2/token', (body) => {\n\t\t\t\t\t\tassert.include(body, expectedBody);\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, {\n\t\t\t\t\t\taccess_token: downscopedToken,\n\t\t\t\t\t\texpires_in: 256,\n\t\t\t\t\t})\n\t\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'tokens:exchange',\n\t\t\t\tscopes.join(','),\n\t\t\t\t`--user-id=${userID}`,\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should return token for user when passed --user-id flag',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, `${downscopedToken}${os.EOL}`);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/oauth2/token', (body) => {\n\t\t\t\t\tassert.include(body, expectedBody);\n\t\t\t\t\treturn true;\n\t\t\t\t})\n\t\t\t\t.reply(200, {\n\t\t\t\t\taccess_token: downscopedToken,\n\t\t\t\t\texpires_in: 256,\n\t\t\t\t})\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'tokens:exchange',\n\t\t\t\tscopes.join(','),\n\t\t\t\t`--token=${TEST_ACCESS_TOKEN}`,\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should exchange specified token when --token flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, `${downscopedToken}\\n`);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/trash.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst leche = require('leche');\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\n\ndescribe('Trash', function () {\n\tdescribe('trash:delete', function () {\n\t\tlet itemId = '1234';\n\n\t\tleche.withData(\n\t\t\t{\n\t\t\t\t'file argument': ['file'],\n\t\t\t\t'folder argument': ['folder'],\n\t\t\t\t'web link argument': ['web_link'],\n\t\t\t},\n\t\t\tfunction (itemType) {\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi.delete(`/2.0/${itemType}s/${itemId}/trash`).reply(204)\n\t\t\t\t)\n\t\t\t\t\t.stderr()\n\t\t\t\t\t.command(['trash:delete', itemType, itemId, '--token=test'])\n\t\t\t\t\t.it('should permanently delete an item', (context) => {\n\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t\t`Deleted item ${itemId}${os.EOL}`\n\t\t\t\t\t\t);\n\t\t\t\t\t});\n\t\t\t}\n\t\t);\n\t});\n\n\tleche.withData(['trash', 'trash:list'], function (command) {\n\t\tdescribe(command, function () {\n\t\t\tlet fixture = getFixture('trash/get_trashed_items_page_1'),\n\t\t\t\tfixture2 = getFixture('trash/get_trashed_items_page_2'),\n\t\t\t\tjsonOutput = getFixture('output/trash_list_json.txt');\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/folders/trash/items')\n\t\t\t\t\t.query({ usemarker: true, limit: 1000 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get('/2.0/folders/trash/items')\n\t\t\t\t\t.query({\n\t\t\t\t\t\toffset: 2,\n\t\t\t\t\t\tusemarker: true,\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([command, '--json', '--token=test'])\n\t\t\t\t.it(\n\t\t\t\t\t'should list all items in trash (JSON Output)',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/folders/trash/items')\n\t\t\t\t\t.query({ fields: 'name', usemarker: true, limit: 1000 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get('/2.0/folders/trash/items')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tfields: 'name',\n\t\t\t\t\t\toffset: 2,\n\t\t\t\t\t\tusemarker: true,\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([command, '--fields=name', '--json', '--token=test'])\n\t\t\t\t.it(\n\t\t\t\t\t'should send fields param to the API when --fiels flag is passed'\n\t\t\t\t);\n\t\t});\n\t});\n\n\tdescribe('trash:get', function () {\n\t\tlet folderFixture = getFixture('trash/get_folders_id_trash'),\n\t\t\tfileFixture = getFixture('trash/get_files_id_trash'),\n\t\t\twebLinkFixture = getFixture('trash/get_folders_id_trash');\n\t\tlet itemId = '12345';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/folders/${itemId}/trash`).reply(200, folderFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['trash:get', 'folder', itemId, '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information on a folder in trash (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet fixtureJSON = JSON.parse(folderFixture);\n\t\t\t\t\tlet outputJSON = JSON.parse(context.stdout);\n\t\t\t\t\tassert.deepEqual(outputJSON, fixtureJSON);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/files/${itemId}/trash`).reply(200, fileFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['trash:get', 'file', itemId, '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information on a file in trash (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet fixtureJSON = JSON.parse(fileFixture);\n\t\t\t\t\tlet outputJSON = JSON.parse(context.stdout);\n\t\t\t\t\tassert.deepEqual(outputJSON, fixtureJSON);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/web_links/${itemId}/trash`).reply(200, webLinkFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'trash:get',\n\t\t\t\t'web_link',\n\t\t\t\titemId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get information on a web link in trash (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet fixtureJSON = JSON.parse(webLinkFixture);\n\t\t\t\t\tlet outputJSON = JSON.parse(context.stdout);\n\t\t\t\t\tassert.deepEqual(outputJSON, fixtureJSON);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('trash:restore', function () {\n\t\tlet folderFixture = getFixture('trash/post_folders_id'),\n\t\t\tfileFixture = getFixture('trash/post_files_id'),\n\t\t\twebLinkFixture = getFixture('trash/post_web_links_id');\n\n\t\tlet itemId = '1234',\n\t\t\tname = 'Contracts',\n\t\t\tparentId = '0';\n\n\t\tlet expectedBody = {\n\t\t\tname,\n\t\t\tparent: { id: parentId },\n\t\t};\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/folders/${itemId}`, expectedBody)\n\t\t\t\t.reply(201, folderFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'trash:restore',\n\t\t\t\t'folder',\n\t\t\t\titemId,\n\t\t\t\t`--name=${name}`,\n\t\t\t\t`--parent-id=${parentId}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should restore a folder from trash (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet fixtureJSON = JSON.parse(folderFixture);\n\t\t\t\t\tlet outputJSON = JSON.parse(context.stdout);\n\t\t\t\t\tassert.deepEqual(outputJSON, fixtureJSON);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/files/${itemId}`, expectedBody)\n\t\t\t\t.reply(201, fileFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'trash:restore',\n\t\t\t\t'file',\n\t\t\t\titemId,\n\t\t\t\t`--name=${name}`,\n\t\t\t\t`--parent-id=${parentId}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should restore a file from trash (JSON Output)', (context) => {\n\t\t\t\tlet fixtureJSON = JSON.parse(fileFixture);\n\t\t\t\tlet outputJSON = JSON.parse(context.stdout);\n\t\t\t\tassert.deepEqual(outputJSON, fixtureJSON);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post(`/2.0/web_links/${itemId}`, expectedBody)\n\t\t\t\t.reply(201, webLinkFixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'trash:restore',\n\t\t\t\t'web_link',\n\t\t\t\titemId,\n\t\t\t\t`--name=${name}`,\n\t\t\t\t`--parent-id=${parentId}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should restore a web link from trash (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tlet fixtureJSON = JSON.parse(webLinkFixture);\n\t\t\t\t\tlet outputJSON = JSON.parse(context.stdout);\n\t\t\t\t\tassert.deepEqual(outputJSON, fixtureJSON);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/update.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst sinon = require('sinon');\nconst UpdateCommand = require('../../src/commands/update');\nconst GitHubUpdater = require('../../src/github-updater');\n\ndescribe('Update', function () {\n\tlet sandbox;\n\tlet githubUpdaterStub;\n\tlet fetchVersionIndexStub;\n\tlet findLocalVersionsStub;\n\tlet runUpdateStub;\n\n\tbeforeEach(function () {\n\t\tsandbox = sinon.createSandbox();\n\n\t\t// Stub GitHubUpdater methods\n\t\tfetchVersionIndexStub = sandbox.stub();\n\t\tfindLocalVersionsStub = sandbox.stub();\n\t\trunUpdateStub = sandbox.stub();\n\n\t\tgithubUpdaterStub = sandbox.stub(GitHubUpdater.prototype);\n\t\tgithubUpdaterStub.fetchVersionIndex = fetchVersionIndexStub;\n\t\tgithubUpdaterStub.findLocalVersions = findLocalVersionsStub;\n\t\tgithubUpdaterStub.runUpdate = runUpdateStub;\n\t});\n\n\tafterEach(function () {\n\t\tsandbox.restore();\n\t});\n\n\tdescribe('update', function () {\n\t\tit('should list available versions when --available flag is passed', async function () {\n\t\t\tconst mockVersionIndex = {\n\t\t\t\t'3.0.0':\n\t\t\t\t\t'https://github.com/box/boxcli/releases/download/v3.0.0',\n\t\t\t\t'2.5.0':\n\t\t\t\t\t'https://github.com/box/boxcli/releases/download/v2.5.0',\n\t\t\t\t'2.0.0':\n\t\t\t\t\t'https://github.com/box/boxcli/releases/download/v2.0.0',\n\t\t\t};\n\t\t\tconst mockLocalVersions = ['/path/to/3.0.0'];\n\n\t\t\tfetchVersionIndexStub.resolves(mockVersionIndex);\n\t\t\tfindLocalVersionsStub.resolves(mockLocalVersions);\n\n\t\t\tawait test\n\t\t\t\t.stdout()\n\t\t\t\t.stub(\n\t\t\t\t\tGitHubUpdater.prototype,\n\t\t\t\t\t'fetchVersionIndex',\n\t\t\t\t\tfetchVersionIndexStub\n\t\t\t\t)\n\t\t\t\t.stub(\n\t\t\t\t\tGitHubUpdater.prototype,\n\t\t\t\t\t'findLocalVersions',\n\t\t\t\t\tfindLocalVersionsStub\n\t\t\t\t)\n\t\t\t\t.command(['update', '--available'])\n\t\t\t\t.it('displays available versions in table format', (ctx) => {\n\t\t\t\t\t// Verify the stubs were called\n\t\t\t\t\tassert.isTrue(fetchVersionIndexStub.called);\n\t\t\t\t\tassert.isTrue(findLocalVersionsStub.called);\n\t\t\t\t\t// Verify output contains version numbers\n\t\t\t\t\tassert.include(ctx.stdout, '3.0.0');\n\t\t\t\t\tassert.include(ctx.stdout, '2.5.0');\n\t\t\t\t});\n\t\t});\n\n\t\tit('should call runUpdate with correct parameters when updating to specific version', async function () {\n\t\t\trunUpdateStub.resolves();\n\n\t\t\tawait test\n\t\t\t\t.stub(GitHubUpdater.prototype, 'runUpdate', runUpdateStub)\n\t\t\t\t.command(['update', '--version=3.0.0'])\n\t\t\t\t.it('updates to specified version', () => {\n\t\t\t\t\tassert.isTrue(runUpdateStub.called);\n\t\t\t\t\tconst callArgs = runUpdateStub.getCall(0).args[0];\n\t\t\t\t\tassert.equal(callArgs.version, '3.0.0');\n\t\t\t\t\tassert.isFalse(callArgs.autoUpdate);\n\t\t\t\t\tassert.isFalse(callArgs.force);\n\t\t\t\t});\n\t\t});\n\n\t\tit('should call runUpdate with force flag', async function () {\n\t\t\trunUpdateStub.resolves();\n\n\t\t\tawait test\n\t\t\t\t.stub(GitHubUpdater.prototype, 'runUpdate', runUpdateStub)\n\t\t\t\t.command(['update', '--force'])\n\t\t\t\t.it('updates with force flag', () => {\n\t\t\t\t\tassert.isTrue(runUpdateStub.called);\n\t\t\t\t\tconst callArgs = runUpdateStub.getCall(0).args[0];\n\t\t\t\t\tassert.isTrue(callArgs.force);\n\t\t\t\t});\n\t\t});\n\n\t\tit('should call runUpdate with autoupdate flag', async function () {\n\t\t\trunUpdateStub.resolves();\n\n\t\t\tawait test\n\t\t\t\t.stub(GitHubUpdater.prototype, 'runUpdate', runUpdateStub)\n\t\t\t\t.command(['update', '--autoupdate'])\n\t\t\t\t.it('updates with autoupdate flag', () => {\n\t\t\t\t\tassert.isTrue(runUpdateStub.called);\n\t\t\t\t\tconst callArgs = runUpdateStub.getCall(0).args[0];\n\t\t\t\t\tassert.isTrue(callArgs.autoUpdate);\n\t\t\t\t});\n\t\t});\n\n\t\tit('should update to specific channel', async function () {\n\t\t\trunUpdateStub.resolves();\n\n\t\t\tawait test\n\t\t\t\t.stub(GitHubUpdater.prototype, 'runUpdate', runUpdateStub)\n\t\t\t\t.command(['update', 'stable'])\n\t\t\t\t.it('updates to specified channel', () => {\n\t\t\t\t\tassert.isTrue(runUpdateStub.called);\n\t\t\t\t\tconst callArgs = runUpdateStub.getCall(0).args[0];\n\t\t\t\t\tassert.equal(callArgs.channel, 'stable');\n\t\t\t\t});\n\t\t});\n\n\t\tit('should error when both version and channel are specified', async function () {\n\t\t\tawait test\n\t\t\t\t.command(['update', 'stable', '--version=3.0.0'])\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\terror.message,\n\t\t\t\t\t\t'You cannot specify both a version and a channel'\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t\t.it('throws error when both channel and version are provided');\n\t\t});\n\n\t\tit('should handle interactive version selection', async function () {\n\t\t\tconst promptStub = sandbox.stub(\n\t\t\t\tUpdateCommand.prototype,\n\t\t\t\t'promptForVersion'\n\t\t\t);\n\t\t\tpromptStub.resolves('3.0.0');\n\t\t\trunUpdateStub.resolves();\n\n\t\t\tawait test\n\t\t\t\t.stub(UpdateCommand.prototype, 'promptForVersion', promptStub)\n\t\t\t\t.stub(GitHubUpdater.prototype, 'runUpdate', runUpdateStub)\n\t\t\t\t.command(['update', '--interactive'])\n\t\t\t\t.it('prompts for version selection in interactive mode', () => {\n\t\t\t\t\tassert.isTrue(promptStub.called);\n\t\t\t\t\tassert.isTrue(runUpdateStub.called);\n\t\t\t\t\tconst callArgs = runUpdateStub.getCall(0).args[0];\n\t\t\t\t\tassert.equal(callArgs.version, '3.0.0');\n\t\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('update command description', function () {\n\t\tit('should have correct description', function () {\n\t\t\tassert.equal(\n\t\t\t\tUpdateCommand.description,\n\t\t\t\t'Update the BoxCLI using GitHub'\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe('GitHubUpdater integration', function () {\n\t\tit('should instantiate GitHubUpdater with config', async function () {\n\t\t\trunUpdateStub.resolves();\n\n\t\t\tawait test\n\t\t\t\t.stub(GitHubUpdater.prototype, 'runUpdate', runUpdateStub)\n\t\t\t\t.command(['update'])\n\t\t\t\t.it('creates GitHubUpdater instance', () => {\n\t\t\t\t\t// Verify updater was instantiated\n\t\t\t\t\tassert.isTrue(runUpdateStub.called);\n\t\t\t\t});\n\t\t});\n\n\t\tit('should handle update errors gracefully', async function () {\n\t\t\tconst updateError = new Error('Update failed');\n\t\t\trunUpdateStub.rejects(updateError);\n\n\t\t\tawait test\n\t\t\t\t.stub(GitHubUpdater.prototype, 'runUpdate', runUpdateStub)\n\t\t\t\t.command(['update'])\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tassert.include(error.message, 'Update failed');\n\t\t\t\t})\n\t\t\t\t.it('handles update errors');\n\t\t});\n\n\t\tit('should handle version index fetch errors', async function () {\n\t\t\tconst fetchError = new Error('Failed to fetch version index');\n\t\t\tfetchVersionIndexStub.rejects(fetchError);\n\n\t\t\tawait test\n\t\t\t\t.stub(\n\t\t\t\t\tGitHubUpdater.prototype,\n\t\t\t\t\t'fetchVersionIndex',\n\t\t\t\t\tfetchVersionIndexStub\n\t\t\t\t)\n\t\t\t\t.command(['update', '--available'])\n\t\t\t\t.catch((error) => {\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\terror.message,\n\t\t\t\t\t\t'Failed to fetch version index'\n\t\t\t\t\t);\n\t\t\t\t})\n\t\t\t\t.it('handles version index fetch errors');\n\t\t});\n\t});\n\n\tdescribe('update flags combinations', function () {\n\t\tit('should work with version and force flags together', async function () {\n\t\t\trunUpdateStub.resolves();\n\n\t\t\tawait test\n\t\t\t\t.stub(GitHubUpdater.prototype, 'runUpdate', runUpdateStub)\n\t\t\t\t.command(['update', '--version=3.0.0', '--force'])\n\t\t\t\t.it('updates to version with force', () => {\n\t\t\t\t\tassert.isTrue(runUpdateStub.called);\n\t\t\t\t\tconst callArgs = runUpdateStub.getCall(0).args[0];\n\t\t\t\t\tassert.equal(callArgs.version, '3.0.0');\n\t\t\t\t\tassert.isTrue(callArgs.force);\n\t\t\t\t});\n\t\t});\n\n\t\tit('should work with channel and autoupdate flags together', async function () {\n\t\t\trunUpdateStub.resolves();\n\n\t\t\tawait test\n\t\t\t\t.stub(GitHubUpdater.prototype, 'runUpdate', runUpdateStub)\n\t\t\t\t.command(['update', 'stable', '--autoupdate'])\n\t\t\t\t.it('updates to channel with autoupdate', () => {\n\t\t\t\t\tassert.isTrue(runUpdateStub.called);\n\t\t\t\t\tconst callArgs = runUpdateStub.getCall(0).args[0];\n\t\t\t\t\tassert.equal(callArgs.channel, 'stable');\n\t\t\t\t\tassert.isTrue(callArgs.autoUpdate);\n\t\t\t\t});\n\t\t});\n\n\t\tit('should work with interactive and force flags together', async function () {\n\t\t\tconst promptStub = sandbox.stub(\n\t\t\t\tUpdateCommand.prototype,\n\t\t\t\t'promptForVersion'\n\t\t\t);\n\t\t\tpromptStub.resolves('3.5.0');\n\t\t\trunUpdateStub.resolves();\n\n\t\t\tawait test\n\t\t\t\t.stub(UpdateCommand.prototype, 'promptForVersion', promptStub)\n\t\t\t\t.stub(GitHubUpdater.prototype, 'runUpdate', runUpdateStub)\n\t\t\t\t.command(['update', '--interactive', '--force'])\n\t\t\t\t.it('prompts for version with force flag', () => {\n\t\t\t\t\tassert.isTrue(promptStub.called);\n\t\t\t\t\tassert.isTrue(runUpdateStub.called);\n\t\t\t\t\tconst callArgs = runUpdateStub.getCall(0).args[0];\n\t\t\t\t\tassert.equal(callArgs.version, '3.5.0');\n\t\t\t\t\tassert.isTrue(callArgs.force);\n\t\t\t\t});\n\t\t});\n\n\t\tit('should handle autoupdate and force flags together', async function () {\n\t\t\trunUpdateStub.resolves();\n\n\t\t\tawait test\n\t\t\t\t.stub(GitHubUpdater.prototype, 'runUpdate', runUpdateStub)\n\t\t\t\t.command(['update', '--autoupdate', '--force'])\n\t\t\t\t.it('updates with autoupdate and force', () => {\n\t\t\t\t\tassert.isTrue(runUpdateStub.called);\n\t\t\t\t\tconst callArgs = runUpdateStub.getCall(0).args[0];\n\t\t\t\t\tassert.isTrue(callArgs.autoUpdate);\n\t\t\t\t\tassert.isTrue(callArgs.force);\n\t\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('update command without flags', function () {\n\t\tit('should run update without any flags', async function () {\n\t\t\trunUpdateStub.resolves();\n\n\t\t\tawait test\n\t\t\t\t.stub(GitHubUpdater.prototype, 'runUpdate', runUpdateStub)\n\t\t\t\t.command(['update'])\n\t\t\t\t.it('runs update with defaults', () => {\n\t\t\t\t\tassert.isTrue(runUpdateStub.called);\n\t\t\t\t\tconst callArgs = runUpdateStub.getCall(0).args[0];\n\t\t\t\t\tassert.isFalse(callArgs.autoUpdate);\n\t\t\t\t\tassert.isFalse(callArgs.force);\n\t\t\t\t\tassert.isUndefined(callArgs.version);\n\t\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('available versions display', function () {\n\t\tit('should display both local and remote versions', async function () {\n\t\t\tconst mockVersionIndex = {\n\t\t\t\t'4.0.0':\n\t\t\t\t\t'https://github.com/box/boxcli/releases/download/v4.0.0',\n\t\t\t\t'3.5.0':\n\t\t\t\t\t'https://github.com/box/boxcli/releases/download/v3.5.0',\n\t\t\t\t'3.0.0':\n\t\t\t\t\t'https://github.com/box/boxcli/releases/download/v3.0.0',\n\t\t\t};\n\t\t\tconst mockLocalVersions = [\n\t\t\t\t'/path/to/versions/4.0.0-darwin-x64',\n\t\t\t\t'/path/to/versions/3.5.0-darwin-x64',\n\t\t\t];\n\n\t\t\tfetchVersionIndexStub.resolves(mockVersionIndex);\n\t\t\tfindLocalVersionsStub.resolves(mockLocalVersions);\n\n\t\t\tawait test\n\t\t\t\t.stdout()\n\t\t\t\t.stub(\n\t\t\t\t\tGitHubUpdater.prototype,\n\t\t\t\t\t'fetchVersionIndex',\n\t\t\t\t\tfetchVersionIndexStub\n\t\t\t\t)\n\t\t\t\t.stub(\n\t\t\t\t\tGitHubUpdater.prototype,\n\t\t\t\t\t'findLocalVersions',\n\t\t\t\t\tfindLocalVersionsStub\n\t\t\t\t)\n\t\t\t\t.command(['update', '--available'])\n\t\t\t\t.it('displays mixed local and remote versions', (ctx) => {\n\t\t\t\t\tassert.isTrue(fetchVersionIndexStub.called);\n\t\t\t\t\tassert.isTrue(findLocalVersionsStub.called);\n\t\t\t\t\tassert.include(ctx.stdout, '4.0.0');\n\t\t\t\t\tassert.include(ctx.stdout, '3.5.0');\n\t\t\t\t\tassert.include(ctx.stdout, '3.0.0');\n\t\t\t\t});\n\t\t});\n\n\t\tit('should display only remote versions when no local versions', async function () {\n\t\t\tconst mockVersionIndex = {\n\t\t\t\t'2.0.0':\n\t\t\t\t\t'https://github.com/box/boxcli/releases/download/v2.0.0',\n\t\t\t};\n\t\t\tconst mockLocalVersions = [];\n\n\t\t\tfetchVersionIndexStub.resolves(mockVersionIndex);\n\t\t\tfindLocalVersionsStub.resolves(mockLocalVersions);\n\n\t\t\tawait test\n\t\t\t\t.stdout()\n\t\t\t\t.stub(\n\t\t\t\t\tGitHubUpdater.prototype,\n\t\t\t\t\t'fetchVersionIndex',\n\t\t\t\t\tfetchVersionIndexStub\n\t\t\t\t)\n\t\t\t\t.stub(\n\t\t\t\t\tGitHubUpdater.prototype,\n\t\t\t\t\t'findLocalVersions',\n\t\t\t\t\tfindLocalVersionsStub\n\t\t\t\t)\n\t\t\t\t.command(['update', '--available'])\n\t\t\t\t.it('displays only remote versions', (ctx) => {\n\t\t\t\t\tassert.isTrue(fetchVersionIndexStub.called);\n\t\t\t\t\tassert.isTrue(findLocalVersionsStub.called);\n\t\t\t\t\tassert.include(ctx.stdout, '2.0.0');\n\t\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('edge cases', function () {\n\t\tit('should handle empty version index', async function () {\n\t\t\tconst mockVersionIndex = {};\n\t\t\tconst mockLocalVersions = [];\n\n\t\t\tfetchVersionIndexStub.resolves(mockVersionIndex);\n\t\t\tfindLocalVersionsStub.resolves(mockLocalVersions);\n\n\t\t\tawait test\n\t\t\t\t.stdout()\n\t\t\t\t.stub(\n\t\t\t\t\tGitHubUpdater.prototype,\n\t\t\t\t\t'fetchVersionIndex',\n\t\t\t\t\tfetchVersionIndexStub\n\t\t\t\t)\n\t\t\t\t.stub(\n\t\t\t\t\tGitHubUpdater.prototype,\n\t\t\t\t\t'findLocalVersions',\n\t\t\t\t\tfindLocalVersionsStub\n\t\t\t\t)\n\t\t\t\t.command(['update', '--available'])\n\t\t\t\t.it('handles empty version index gracefully', () => {\n\t\t\t\t\tassert.isTrue(fetchVersionIndexStub.called);\n\t\t\t\t\tassert.isTrue(findLocalVersionsStub.called);\n\t\t\t\t});\n\t\t});\n\n\t\tit('should handle promptForVersion returning null', async function () {\n\t\t\tconst promptStub = sandbox.stub(\n\t\t\t\tUpdateCommand.prototype,\n\t\t\t\t'promptForVersion'\n\t\t\t);\n\t\t\tpromptStub.resolves(null);\n\t\t\trunUpdateStub.resolves();\n\n\t\t\tawait test\n\t\t\t\t.stub(UpdateCommand.prototype, 'promptForVersion', promptStub)\n\t\t\t\t.stub(GitHubUpdater.prototype, 'runUpdate', runUpdateStub)\n\t\t\t\t.command(['update', '--interactive'])\n\t\t\t\t.it('handles null version from prompt', () => {\n\t\t\t\t\tassert.isTrue(promptStub.called);\n\t\t\t\t\tassert.isTrue(runUpdateStub.called);\n\t\t\t\t\tconst callArgs = runUpdateStub.getCall(0).args[0];\n\t\t\t\t\tassert.isNull(callArgs.version);\n\t\t\t\t});\n\t\t});\n\n\t\tit('should handle version with special characters in basename matching', async function () {\n\t\t\tconst mockVersionIndex = {\n\t\t\t\t'1.0.0-beta':\n\t\t\t\t\t'https://github.com/box/boxcli/releases/download/v1.0.0-beta',\n\t\t\t};\n\t\t\tconst mockLocalVersions = [\n\t\t\t\t'/path/to/versions/1.0.0-beta-darwin-x64',\n\t\t\t];\n\n\t\t\tfetchVersionIndexStub.resolves(mockVersionIndex);\n\t\t\tfindLocalVersionsStub.resolves(mockLocalVersions);\n\n\t\t\tawait test\n\t\t\t\t.stdout()\n\t\t\t\t.stub(\n\t\t\t\t\tGitHubUpdater.prototype,\n\t\t\t\t\t'fetchVersionIndex',\n\t\t\t\t\tfetchVersionIndexStub\n\t\t\t\t)\n\t\t\t\t.stub(\n\t\t\t\t\tGitHubUpdater.prototype,\n\t\t\t\t\t'findLocalVersions',\n\t\t\t\t\tfindLocalVersionsStub\n\t\t\t\t)\n\t\t\t\t.command(['update', '--available'])\n\t\t\t\t.it('matches version with special characters', (ctx) => {\n\t\t\t\t\tassert.include(ctx.stdout, '1.0.0-beta');\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\tctx.stdout,\n\t\t\t\t\t\t'/path/to/versions/1.0.0-beta-darwin-x64'\n\t\t\t\t\t);\n\t\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('command class properties', function () {\n\t\tit('should have empty args array', function () {\n\t\t\tassert.isArray(UpdateCommand.args);\n\t\t\tassert.isEmpty(UpdateCommand.args);\n\t\t});\n\n\t\tit('should have examples without the first one', function () {\n\t\t\t// UpdateCommand.examples should have examples, just with the first one removed\n\t\t\tassert.isArray(UpdateCommand.examples);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/commands/users.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst leche = require('leche');\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\n\ndescribe('Users', function () {\n\tleche.withData(\n\t\t['users:email-aliases:add', 'users:add-email-alias'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet userId = '1234',\n\t\t\t\t\temail = 'testuser@example.com',\n\t\t\t\t\tfixture = getFixture('users/post_users_id_email_aliases'),\n\t\t\t\t\tyamlOutput = getFixture(\n\t\t\t\t\t\t'output/users_add_email_alias_yaml.txt'\n\t\t\t\t\t);\n\n\t\t\t\tlet expectedBody = {\n\t\t\t\t\temail,\n\t\t\t\t\tis_confirmed: false,\n\t\t\t\t};\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post(\n\t\t\t\t\t\t\t`/2.0/users/${userId}/email_aliases`,\n\t\t\t\t\t\t\texpectedBody\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.reply(201, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, userId, email, '--json', '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should add a new email alias to a user (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post(\n\t\t\t\t\t\t\t`/2.0/users/${userId}/email_aliases`,\n\t\t\t\t\t\t\texpectedBody\n\t\t\t\t\t\t)\n\t\t\t\t\t\t.reply(201, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, userId, email, '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should add a new email alias to a user (YAML Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post(`/2.0/users/${userId}/email_aliases`, {\n\t\t\t\t\t\t\t...expectedBody,\n\t\t\t\t\t\t\tis_confirmed: true,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(201, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tuserId,\n\t\t\t\t\t\temail,\n\t\t\t\t\t\t'--confirm',\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should auto-confirm email alias when --confirm flag is passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tleche.withData(\n\t\t['users:email-aliases', 'users:get-email-aliases'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet userId = '1234',\n\t\t\t\t\tfixture = getFixture('users/get_users_id_email_aliases'),\n\t\t\t\t\tjsonOutput = getFixture(\n\t\t\t\t\t\t'output/users_get_email_aliases_json.txt'\n\t\t\t\t\t),\n\t\t\t\t\ttableOutput = getFixture(\n\t\t\t\t\t\t'output/users_get_email_aliases_table.txt'\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/users/${userId}/email_aliases`)\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, userId, '--json', '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should get all Email Aliases for a User (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get(`/2.0/users/${userId}/email_aliases`)\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, userId, '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should get all Email Aliases for a User (Table Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, tableOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tleche.withData(\n\t\t['users:email-aliases:remove', 'users:delete-email-alias'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet userId = '1234',\n\t\t\t\t\taliasId = '7777';\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.delete(`/2.0/users/${userId}/email_aliases/${aliasId}`)\n\t\t\t\t\t\t.reply(204)\n\t\t\t\t)\n\t\t\t\t\t.stderr()\n\t\t\t\t\t.command([command, userId, aliasId, '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should delete an email alias from a user',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t\t\t`Removed alias ${aliasId} from user ${userId}${os.EOL}`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tdescribe('users:get', function () {\n\t\tlet userId = '33333',\n\t\t\tfixture = getFixture('users/get_users_id'),\n\t\t\tyamlOutput = getFixture('output/users_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/users/${userId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['users:get', userId, '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a Box user (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/users/${userId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['users:get', userId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a Box user (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get(`/2.0/users/${userId}`)\n\t\t\t\t.query({ fields: 'name,address' })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'users:get',\n\t\t\t\tuserId,\n\t\t\t\t'--fields=name,address',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\t});\n\n\tleche.withData(['users', 'users:list'], function (command) {\n\t\tdescribe(command, function () {\n\t\t\tlet fixture = getFixture('users/get_users_page_1'),\n\t\t\t\tfixture2 = getFixture('users/get_users_page_2'),\n\t\t\t\tjsonOutput = getFixture('output/users_list_json.txt');\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/users')\n\t\t\t\t\t.query({ filter_term: 'AppUser_', limit: 1000 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get('/2.0/users')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tfilter_term: 'AppUser_',\n\t\t\t\t\t\toffset: 3,\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([command, '--app-users', '--json', '--token=test'])\n\t\t\t\t.it(\n\t\t\t\t\t'should list all Box users with the app-users flag passed (JSON Output)',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/users')\n\t\t\t\t\t.query({ fields: 'name,address', limit: 1000 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get('/2.0/users')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tfields: 'name,address',\n\t\t\t\t\t\toffset: 3,\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\t'--fields=name,address',\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t\t);\n\t\t});\n\t});\n\n\tleche.withData(['users:groups', 'users:list-groups'], function (command) {\n\t\tdescribe(command, function () {\n\t\t\tlet userId = '13130406',\n\t\t\t\tfixture = getFixture('users/get_users_id_memberships_page_1'),\n\t\t\t\tfixture2 = getFixture('users/get_users_id_memberships_page_2'),\n\t\t\t\tjsonOutput = getFixture('output/users_list_groups_json.txt');\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get(`/2.0/users/${userId}/memberships`)\n\t\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get(`/2.0/users/${userId}/memberships`)\n\t\t\t\t\t.query({\n\t\t\t\t\t\toffset: 1,\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([command, userId, '--json', '--token=test'])\n\t\t\t\t.it(\n\t\t\t\t\t'should list groups a user belongs to (JSON Output)',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get(`/2.0/users/${userId}/memberships`)\n\t\t\t\t\t.query({ fields: 'name', limit: 1000 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get(`/2.0/users/${userId}/memberships`)\n\t\t\t\t\t.query({\n\t\t\t\t\t\tfields: 'name',\n\t\t\t\t\t\toffset: 1,\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\tuserId,\n\t\t\t\t\t'--fields=name',\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t\t);\n\t\t});\n\t});\n\n\tdescribe('users:search', function () {\n\t\tlet userName = 'roger federer',\n\t\t\tfixture = getFixture('users/get_users_page_1'),\n\t\t\tfixture2 = getFixture('users/get_users_page_2'),\n\t\t\tjsonOutput = getFixture('output/users_search_json.txt'),\n\t\t\tjsonFieldsOutput = getFixture(\n\t\t\t\t'output/users_search_fields_json.txt'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/users')\n\t\t\t\t.query({\n\t\t\t\t\tfilter_term: userName,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/users')\n\t\t\t\t.query({\n\t\t\t\t\tfilter_term: userName,\n\t\t\t\t\toffset: 3,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['users:search', userName, '--json', '--token=test'])\n\t\t\t.it('should search for Box users (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/users')\n\t\t\t\t.query({\n\t\t\t\t\tfields: 'name,address',\n\t\t\t\t\tfilter_term: userName,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/users')\n\t\t\t\t.query({\n\t\t\t\t\tfields: 'name,address',\n\t\t\t\t\tfilter_term: userName,\n\t\t\t\t\toffset: 3,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'users:search',\n\t\t\t\tuserName,\n\t\t\t\t'--fields=name,address',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should send fields param to the API when --fields flag is passed'\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.get('/2.0/users')\n\t\t\t\t.query({\n\t\t\t\t\tfilter_term: userName,\n\t\t\t\t\tfields: 'name,tracking_codes,is_external_collab_restricted',\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t\t\t.get('/2.0/users')\n\t\t\t\t.query({\n\t\t\t\t\tfilter_term: userName,\n\t\t\t\t\tfields: 'name,tracking_codes,is_external_collab_restricted',\n\t\t\t\t\toffset: 3,\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture2)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'users:search',\n\t\t\t\tuserName,\n\t\t\t\t'--fields=name,tracking_codes,is_external_collab_restricted',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should request specific fields from API when fields flag is passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonFieldsOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\tleche.withData(\n\t\t\t{\n\t\t\t\t'managed users flag': [\n\t\t\t\t\t'--managed-users',\n\t\t\t\t\t{ user_type: 'managed' },\n\t\t\t\t],\n\t\t\t\t'external users flag': [\n\t\t\t\t\t'--external-users',\n\t\t\t\t\t{ user_type: 'external' },\n\t\t\t\t],\n\t\t\t\t'all users flag': ['--all-users', { user_type: 'all' }],\n\t\t\t},\n\t\t\tfunction (flag, queryParameters) {\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.get('/2.0/users')\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\tfilter_term: userName,\n\t\t\t\t\t\t\t...queryParameters,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t\t.get('/2.0/users')\n\t\t\t\t\t\t.query({\n\t\t\t\t\t\t\tfilter_term: userName,\n\t\t\t\t\t\t\t...queryParameters,\n\t\t\t\t\t\t\toffset: 3,\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.reply(200, fixture2)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\t'users:search',\n\t\t\t\t\t\tuserName,\n\t\t\t\t\t\tflag,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should search for correct type of users when filtering flag is passed (JSON Output)',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t}\n\t\t);\n\t});\n\n\tleche.withData(['users:invite', 'users:invite-user'], function (command) {\n\t\tdescribe(command, function () {\n\t\t\tlet userEmail = 'testuser@example.com',\n\t\t\t\tenterpriseId = '1234',\n\t\t\t\tfixture = getFixture('users/get_users_id'),\n\t\t\t\tyamlOutput = getFixture('output/users_invite_user_yaml.txt');\n\n\t\t\tlet expectedBody = {\n\t\t\t\tenterprise: { id: enterpriseId },\n\t\t\t\tactionable_by: { login: userEmail },\n\t\t\t};\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi.post('/2.0/invites', expectedBody).reply(201, fixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\tcommand,\n\t\t\t\t\tuserEmail,\n\t\t\t\t\tenterpriseId,\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--token=test',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should invite an Existing Box User to Your Enterprise (JSON Output)',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi.post('/2.0/invites', expectedBody).reply(201, fixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([command, userEmail, enterpriseId, '--token=test'])\n\t\t\t\t.it(\n\t\t\t\t\t'should invite an Existing Box User to Your Enterprise (YAML Output)',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t});\n\t});\n\n\tleche.withData(\n\t\t['users:transfer-content', 'users:move-root-content'],\n\t\tfunction (command) {\n\t\t\tdescribe(command, function () {\n\t\t\t\tlet userId = '1234',\n\t\t\t\t\tnewUserId = '4321',\n\t\t\t\t\tfixture = getFixture('users/put_users_id_folder'),\n\t\t\t\t\tyamlOutput = getFixture(\n\t\t\t\t\t\t'output/users_move_root_content_yaml.txt'\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(`/2.0/users/${userId}/folders/0`)\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\tcommand,\n\t\t\t\t\t\tuserId,\n\t\t\t\t\t\tnewUserId,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t\"should move a user's root content to another user (JSON Output)\",\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(`/2.0/users/${userId}/folders/0`)\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, userId, newUserId, '--token=test'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t\"should move a user's root content to another user (YAML Output)\",\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.put(`/2.0/users/${userId}/folders/0`)\n\t\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([command, userId, newUserId, '--token=test', '-q'])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t\"should move a user's root content to another user (No Output)\",\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.isEmpty(context.stdout);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t});\n\t\t}\n\t);\n\n\tdescribe('users:create', function () {\n\t\tlet name = 'Another Test User',\n\t\t\tlogin = 'anothertestuser@example.com',\n\t\t\trole = 'user',\n\t\t\tphone = '1234567890',\n\t\t\tfixture = getFixture('users/post_users'),\n\t\t\tyamlOutput = getFixture('output/users_create_yaml.txt');\n\n\t\tlet expectedBody = {\n\t\t\tname,\n\t\t\tlogin,\n\t\t\tphone,\n\t\t\trole,\n\t\t\tis_sync_enabled: true,\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/users', expectedBody).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'users:create',\n\t\t\t\tname,\n\t\t\t\tlogin,\n\t\t\t\t`--role=${role}`,\n\t\t\t\t`--phone-number=${phone}`,\n\t\t\t\t'--sync-enable',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a new Box user with role, phone-number and sync-enable flags passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/users', expectedBody).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'users:create',\n\t\t\t\tname,\n\t\t\t\tlogin,\n\t\t\t\t`--role=${role}`,\n\t\t\t\t`--phone-number=${phone}`,\n\t\t\t\t'--sync-enable',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a new Box user with role, phone-number and sync-enable flags passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/users', expectedBody).reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'users:create',\n\t\t\t\tname,\n\t\t\t\tlogin,\n\t\t\t\t`--role=${role}`,\n\t\t\t\t`--phone-number=${phone}`,\n\t\t\t\t'--sync-enable',\n\t\t\t\t'--id-only',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a new Box user with role, phone-number and sync-enable flags passed (ID Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.parse(fixture).id}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\tleche.withData(\n\t\t\t{\n\t\t\t\t'sync disable flag': [\n\t\t\t\t\t'--no-sync-enable',\n\t\t\t\t\t{ is_sync_enabled: false },\n\t\t\t\t],\n\t\t\t\t'exempt from device limits flag': [\n\t\t\t\t\t'--exempt-from-device-limits',\n\t\t\t\t\t{ is_exempt_from_device_limits: true },\n\t\t\t\t],\n\t\t\t\t'no exempt from device limits flag': [\n\t\t\t\t\t'--no-exempt-from-device-limits',\n\t\t\t\t\t{ is_exempt_from_device_limits: false },\n\t\t\t\t],\n\t\t\t\t'password reset required flag': [\n\t\t\t\t\t'--password-reset',\n\t\t\t\t\t{ is_password_reset_required: true },\n\t\t\t\t],\n\t\t\t\t'exempt from login verification flag': [\n\t\t\t\t\t'--exempt-from-2fa',\n\t\t\t\t\t{ is_exempt_from_login_verification: true },\n\t\t\t\t],\n\t\t\t\t'no exempt from login verification flag': [\n\t\t\t\t\t'--no-exempt-from-2fa',\n\t\t\t\t\t{ is_exempt_from_login_verification: false },\n\t\t\t\t],\n\t\t\t\t'external collab restricted flag': [\n\t\t\t\t\t'--restrict-external-collab',\n\t\t\t\t\t{ is_external_collab_restricted: true },\n\t\t\t\t],\n\t\t\t\t'can see managed users flag': [\n\t\t\t\t\t'--can-see-managed-users',\n\t\t\t\t\t{ can_see_managed_users: true },\n\t\t\t\t],\n\t\t\t\t'no can see managed users flag': [\n\t\t\t\t\t'--no-can-see-managed-users',\n\t\t\t\t\t{ can_see_managed_users: false },\n\t\t\t\t],\n\t\t\t\t'language flag': ['--language=en-us', { language: 'en-us' }],\n\t\t\t\t'job title flag': ['--job-title=CEO', { job_title: 'CEO' }],\n\t\t\t\t'address flag': ['--address=Nowhere', { address: 'Nowhere' }],\n\t\t\t\t'space amount flag': [\n\t\t\t\t\t'--disk-space=12345',\n\t\t\t\t\t{ space_amount: 12_345 },\n\t\t\t\t],\n\t\t\t\t'status flag': ['--status=inactive', { status: 'inactive' }],\n\t\t\t\t'timezone flag': [\n\t\t\t\t\t'--timezone=America/Los_Angeles',\n\t\t\t\t\t{ timezone: 'America/Los_Angeles' },\n\t\t\t\t],\n\t\t\t\t'tracking codes': [\n\t\t\t\t\t'--tracking-codes=name1=value1,name2=value2',\n\t\t\t\t\t{\n\t\t\t\t\t\ttracking_codes: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'tracking_code',\n\t\t\t\t\t\t\t\tname: 'name1',\n\t\t\t\t\t\t\t\tvalue: 'value1',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'tracking_code',\n\t\t\t\t\t\t\t\tname: 'name2',\n\t\t\t\t\t\t\t\tvalue: 'value2',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\tfunction (flag, body) {\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.post('/2.0/users', { name, login, ...body })\n\t\t\t\t\t\t.reply(201, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\t'users:create',\n\t\t\t\t\t\tname,\n\t\t\t\t\t\tlogin,\n\t\t\t\t\t\tflag,\n\t\t\t\t\t\t'--id-only',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should create a new Box user with specified attributes when flag is passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t\t\t`${JSON.parse(fixture).id}${os.EOL}`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t}\n\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/users', {\n\t\t\t\t\tname,\n\t\t\t\t\tis_platform_access_only: true,\n\t\t\t\t\texternal_app_user_id: 'foo',\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'users:create',\n\t\t\t\tname,\n\t\t\t\t'--app-user',\n\t\t\t\t'--external-id=foo',\n\t\t\t\t'--id-only',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a new app user with external ID when App User flags are passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t\t`${JSON.parse(fixture).id}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.stdout()\n\t\t\t.stderr()\n\t\t\t.command(['users:create', name, '--no-color', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should output an error message when neither the --app-user flag or login is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, '');\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Either the login argument or the --app-user flag is required${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('users:update', function () {\n\t\tlet userId = '33333',\n\t\t\tphone = '(555) 555-5555',\n\t\t\tjobTitle = 'CEO',\n\t\t\tfixture = getFixture('users/put_users_id'),\n\t\t\tyamlOutput = getFixture('output/users_update_yaml.txt');\n\n\t\tlet expectedBody = {\n\t\t\tphone,\n\t\t\tjob_title: jobTitle,\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.put(`/2.0/users/${userId}`, expectedBody).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'users:update',\n\t\t\t\tuserId,\n\t\t\t\t`--phone-number=${phone}`,\n\t\t\t\t`--job-title=${jobTitle}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a new Box user with phone-number and job-title flags passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.put(`/2.0/users/${userId}`, expectedBody).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'users:update',\n\t\t\t\tuserId,\n\t\t\t\t`--phone-number=${phone}`,\n\t\t\t\t`--job-title=${jobTitle}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a new Box user with phone-number and job-title flags passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\tleche.withData(\n\t\t\t{\n\t\t\t\t'sync disable flag': [\n\t\t\t\t\t'--no-sync-enable',\n\t\t\t\t\t{ is_sync_enabled: false },\n\t\t\t\t],\n\t\t\t\t'exempt from device limits flag': [\n\t\t\t\t\t'--exempt-from-device-limits',\n\t\t\t\t\t{ is_exempt_from_device_limits: true },\n\t\t\t\t],\n\t\t\t\t'no exempt from device limits flag': [\n\t\t\t\t\t'--no-exempt-from-device-limits',\n\t\t\t\t\t{ is_exempt_from_device_limits: false },\n\t\t\t\t],\n\t\t\t\t'password reset required flag': [\n\t\t\t\t\t'--password-reset',\n\t\t\t\t\t{ is_password_reset_required: true },\n\t\t\t\t],\n\t\t\t\t'exempt from login verification flag': [\n\t\t\t\t\t'--exempt-from-2fa',\n\t\t\t\t\t{ is_exempt_from_login_verification: true },\n\t\t\t\t],\n\t\t\t\t'no exempt from login verification flag': [\n\t\t\t\t\t'--no-exempt-from-2fa',\n\t\t\t\t\t{ is_exempt_from_login_verification: false },\n\t\t\t\t],\n\t\t\t\t'external collab restricted flag': [\n\t\t\t\t\t'--restrict-external-collab',\n\t\t\t\t\t{ is_external_collab_restricted: true },\n\t\t\t\t],\n\t\t\t\t'can see managed users flag': [\n\t\t\t\t\t'--can-see-managed-users',\n\t\t\t\t\t{ can_see_managed_users: true },\n\t\t\t\t],\n\t\t\t\t'no can see managed users flag': [\n\t\t\t\t\t'--no-can-see-managed-users',\n\t\t\t\t\t{ can_see_managed_users: false },\n\t\t\t\t],\n\t\t\t\t'language flag': ['--language=en-us', { language: 'en-us' }],\n\t\t\t\t'job title flag': ['--job-title=CEO', { job_title: 'CEO' }],\n\t\t\t\t'address flag': ['--address=Nowhere', { address: 'Nowhere' }],\n\t\t\t\t'space amount flag': [\n\t\t\t\t\t'--disk-space=12345',\n\t\t\t\t\t{ space_amount: 12_345 },\n\t\t\t\t],\n\t\t\t\t'status flag': ['--status=inactive', { status: 'inactive' }],\n\t\t\t\t'timezone flag': [\n\t\t\t\t\t'--timezone=America/Los_Angeles',\n\t\t\t\t\t{ timezone: 'America/Los_Angeles' },\n\t\t\t\t],\n\t\t\t\t'role flag': ['--role=coadmin', { role: 'coadmin' }],\n\t\t\t\t'remove flag': ['--remove', { enterprise: null }],\n\t\t\t\t'login flag': [\n\t\t\t\t\t'--login=new.email@gmail.com',\n\t\t\t\t\t{ login: 'new.email@gmail.com' },\n\t\t\t\t],\n\t\t\t\t'name flag': ['--name=Bob Smith', { name: 'Bob Smith' }],\n\t\t\t\t'external ID flag': [\n\t\t\t\t\t'--external-id=foo',\n\t\t\t\t\t{ external_app_user_id: 'foo' },\n\t\t\t\t],\n\t\t\t\t'tracking codes': [\n\t\t\t\t\t'--tracking-codes=name1=value1,name2=value2',\n\t\t\t\t\t{\n\t\t\t\t\t\ttracking_codes: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'tracking_code',\n\t\t\t\t\t\t\t\tname: 'name1',\n\t\t\t\t\t\t\t\tvalue: 'value1',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\ttype: 'tracking_code',\n\t\t\t\t\t\t\t\tname: 'name2',\n\t\t\t\t\t\t\t\tvalue: 'value2',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'notification email flag': [\n\t\t\t\t\t'--notification-email=notify@example.com',\n\t\t\t\t\t{ notification_email: { email: 'notify@example.com' } },\n\t\t\t\t],\n\t\t\t\t'notification email remove flag': [\n\t\t\t\t\t'--notification-email=',\n\t\t\t\t\t{ notification_email: null },\n\t\t\t\t],\n\t\t\t},\n\t\t\tfunction (flag, body) {\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi.put(`/2.0/users/${userId}`, body).reply(200, fixture)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.command([\n\t\t\t\t\t\t'users:update',\n\t\t\t\t\t\tuserId,\n\t\t\t\t\t\tflag,\n\t\t\t\t\t\t'--json',\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should update user with specified attributes when flag is passed',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t}\n\t\t);\n\t});\n\n\tdescribe('users:delete', function () {\n\t\tlet userId = '44444';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.delete(`/2.0/users/${userId}`).query({ force: true }).reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['users:delete', userId, '--force', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should delete a Box User with the force flag passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Deleted user ${userId}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.delete(`/2.0/users/${userId}`)\n\t\t\t\t.query({ notify: false })\n\t\t\t\t.reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['users:delete', userId, '--no-notify', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should pass notify param when --no-notify flag is passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(\n\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t`Deleted user ${userId}${os.EOL}`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('users:terminate-session', function () {\n\t\tlet userIDs = ['12345', '67890'];\n\t\tlet userLogins = ['user1@example.com', 'user2@example.com'];\n\t\tlet fixture = getFixture('users/post_users_terminate_sessions');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/users/terminate_sessions', {\n\t\t\t\t\tuser_ids: userIDs,\n\t\t\t\t\tuser_logins: userLogins,\n\t\t\t\t})\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'users:terminate-session',\n\t\t\t\t'--user-ids',\n\t\t\t\t'12345',\n\t\t\t\t'67890',\n\t\t\t\t'--user-logins',\n\t\t\t\t'user1@example.com',\n\t\t\t\t'user2@example.com',\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should terminate sessions for the specified users',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/watermarking.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst { assert } = require('chai');\nconst leche = require('leche');\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\n\ndescribe('Watermarking', function () {\n\tdescribe('watermarking:apply', function () {\n\t\tlet itemID = '11111',\n\t\t\tfixture = getFixture('watermarking/put_files_id_watermark'),\n\t\t\tyamlOutput = getFixture('output/watermarking_apply_yaml.txt');\n\n\t\tlet expectedBody = {\n\t\t\twatermark: {\n\t\t\t\timprint: 'default',\n\t\t\t},\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/files/${itemID}/watermark`, expectedBody)\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'watermarking:apply',\n\t\t\t\t'file',\n\t\t\t\titemID,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should apply a watermark on a file (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/files/${itemID}/watermark`, expectedBody)\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['watermarking:apply', 'file', itemID, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should apply a watermark on a file (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/folders/${itemID}/watermark`, expectedBody)\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'watermarking:apply',\n\t\t\t\t'folder',\n\t\t\t\titemID,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should apply a watermark on a folder (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('watermarking:get', function () {\n\t\tlet itemID = '11111',\n\t\t\tfixture = getFixture('watermarking/get_files_id_watermark'),\n\t\t\tyamlOutput = getFixture('output/watermarking_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/files/${itemID}/watermark`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'watermarking:get',\n\t\t\t\t'file',\n\t\t\t\titemID,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get the watermark on a file (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/files/${itemID}/watermark`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['watermarking:get', 'file', itemID, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get the watermark on a file (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/folders/${itemID}/watermark`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'watermarking:get',\n\t\t\t\t'folder',\n\t\t\t\titemID,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should get the watermark on a folder (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('watermarking:remove', function () {\n\t\tlet itemID = '11111';\n\n\t\tleche.withData(\n\t\t\t{\n\t\t\t\t'file type': ['file'],\n\t\t\t\t'folder type': ['folder'],\n\t\t\t},\n\t\t\tfunction (itemType) {\n\t\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\t\tapi\n\t\t\t\t\t\t.delete(`/2.0/${itemType}s/${itemID}/watermark`)\n\t\t\t\t\t\t.reply(204)\n\t\t\t\t)\n\t\t\t\t\t.stdout()\n\t\t\t\t\t.stderr()\n\t\t\t\t\t.command([\n\t\t\t\t\t\t'watermarking:remove',\n\t\t\t\t\t\titemType,\n\t\t\t\t\t\titemID,\n\t\t\t\t\t\t'--token=test',\n\t\t\t\t\t])\n\t\t\t\t\t.it(\n\t\t\t\t\t\t'should remove a watermark from the item',\n\t\t\t\t\t\t(context) => {\n\t\t\t\t\t\t\tassert.equal(\n\t\t\t\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t\t\t\t`Removed watermark for ${itemType} ${itemID}${os.EOL}`\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t);\n\t\t\t}\n\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/commands/web-links.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\n\ndescribe('Web Links', function () {\n\tdescribe('web-links:get', function () {\n\t\tlet webLinkId = '6742981',\n\t\t\tfixture = getFixture('web-links/get_web_links_id'),\n\t\t\tyamlOutput = getFixture('output/web_links_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/web_links/${webLinkId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['web-links:get', webLinkId, '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a web link (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/web_links/${webLinkId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['web-links:get', webLinkId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a web link (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('web-links:create', function () {\n\t\tlet url = 'https://www.box.com',\n\t\t\tparentId = '848123342',\n\t\t\tname = 'Box Website!',\n\t\t\tdescription = 'The Box marketing site',\n\t\t\tfixture = getFixture('web-links/post_web_links'),\n\t\t\tyamlOutput = getFixture('output/web_links_create_yaml.txt');\n\n\t\tlet expectedBody = {\n\t\t\tparent: { id: parentId },\n\t\t\turl,\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/web_links', { ...expectedBody, name })\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'web-links:create',\n\t\t\t\turl,\n\t\t\t\t`--parent-id=${parentId}`,\n\t\t\t\t`-n=${name}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a web link with the name flag passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/web_links', { ...expectedBody, name })\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'web-links:create',\n\t\t\t\turl,\n\t\t\t\t`--parent-id=${parentId}`,\n\t\t\t\t`-n=${name}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a web link with the name flag passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.post('/2.0/web_links', { ...expectedBody, description })\n\t\t\t\t.reply(201, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'web-links:create',\n\t\t\t\turl,\n\t\t\t\t`--parent-id=${parentId}`,\n\t\t\t\t`--description=${description}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should create a web link with the description flag passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('web-links:update', function () {\n\t\tlet webLinkId = '6742981',\n\t\t\turl = 'https://www.box.com',\n\t\t\tname = 'Box Website!',\n\t\t\tdescription = 'The Box marketing site',\n\t\t\tfixture = getFixture('web-links/put_web_links_id'),\n\t\t\tyamlOutput = getFixture('output/web_links_update_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/web_links/${webLinkId}`, { name, url })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'web-links:update',\n\t\t\t\twebLinkId,\n\t\t\t\t`-u=${url}`,\n\t\t\t\t`-n=${name}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a web link with url and name flags passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/web_links/${webLinkId}`, { name, url })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'web-links:update',\n\t\t\t\twebLinkId,\n\t\t\t\t`-u=${url}`,\n\t\t\t\t`-n=${name}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a web link with url and name flags passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/web_links/${webLinkId}`, { description })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'web-links:update',\n\t\t\t\twebLinkId,\n\t\t\t\t`--description=${description}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a web link with description flag passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tdescribe('web-links:move', function () {\n\t\tlet webLinkId = '6742981',\n\t\t\tparentFolderId = '848123342',\n\t\t\tfixture = getFixture('web-links/put_web_links_id'),\n\t\t\tyamlOutput = getFixture('output/web_links_move_yaml.txt');\n\n\t\tlet expectedBody = {\n\t\t\tparent: { id: parentFolderId },\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/web_links/${webLinkId}`, expectedBody)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'web-links:move',\n\t\t\t\twebLinkId,\n\t\t\t\tparentFolderId,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should move a web link (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/web_links/${webLinkId}`, expectedBody)\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'web-links:move',\n\t\t\t\twebLinkId,\n\t\t\t\tparentFolderId,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should move a web link (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\t});\n\n\tdescribe('web-links:delete', function () {\n\t\tlet webLinkId = '6742981';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.delete(`/2.0/web_links/${webLinkId}`).reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['web-links:delete', webLinkId, '--token=test'])\n\t\t\t.it('should delete a weblink', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Deleted weblink ${webLinkId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/commands/webhooks.test.js",
    "content": "'use strict';\n\nconst { test } = require('@oclif/test');\nconst assert = require('chai').assert;\nconst { getFixture, TEST_API_ROOT } = require('../helpers/test-helper');\nconst os = require('node:os');\nconst leche = require('leche');\n\ndescribe('Webhooks', function () {\n\tdescribe('webhooks:get', function () {\n\t\tlet webhookId = '1234',\n\t\t\tfixture = getFixture('webhooks/get_webhooks_id'),\n\t\t\tyamlOutput = getFixture('output/webhooks_get_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/webhooks/${webhookId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['webhooks:get', webhookId, '--json', '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a webhook (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.get(`/2.0/webhooks/${webhookId}`).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command(['webhooks:get', webhookId, '--token=test'])\n\t\t\t.it(\n\t\t\t\t'should get information about a webhook (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\t});\n\n\tleche.withData(['webhooks', 'webhooks:list'], function (command) {\n\t\tdescribe(command, function () {\n\t\t\tlet fixture = getFixture('webhooks/get_webhooks_page_1'),\n\t\t\t\tfixture2 = getFixture('webhooks/get_webhooks_page_2'),\n\t\t\t\tjsonOutput = getFixture('output/webhooks_list_json.txt');\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get('/2.0/webhooks')\n\t\t\t\t\t.query({ limit: 1000 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t\t\t.get('/2.0/webhooks')\n\t\t\t\t\t.query({\n\t\t\t\t\t\tmarker: 'ZmlQZS0xLTE%3D',\n\t\t\t\t\t\tlimit: 1000,\n\t\t\t\t\t})\n\t\t\t\t\t.reply(200, fixture2)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([command, '--json', '--token=test'])\n\t\t\t\t.it('should list all webhooks (JSON Output)', (context) => {\n\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('webhooks:delete', function () {\n\t\tlet webhookId = '1234';\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.delete(`/2.0/webhooks/${webhookId}`).reply(204)\n\t\t)\n\t\t\t.stderr()\n\t\t\t.command(['webhooks:delete', webhookId, '--token=test'])\n\t\t\t.it('should delete a webhook', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stderr,\n\t\t\t\t\t`Deleted webhook ${webhookId}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tdescribe('webhooks:create', function () {\n\t\tlet id = '1234',\n\t\t\ttype = 'file',\n\t\t\ttriggers = 'FILE.DOWNLOADED,FILE.UPLOADED',\n\t\t\taddress = 'https://dev.name/actions/file_changed',\n\t\t\tfixture = getFixture('webhooks/post_webhooks'),\n\t\t\tyamlOutput = getFixture('output/webhooks_create_yaml.txt');\n\n\t\tlet expectedBody = {\n\t\t\ttarget: {\n\t\t\t\tid,\n\t\t\t\ttype,\n\t\t\t},\n\t\t\ttriggers: ['FILE.DOWNLOADED', 'FILE.UPLOADED'],\n\t\t\taddress,\n\t\t};\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/webhooks', expectedBody).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'webhooks:create',\n\t\t\t\ttype,\n\t\t\t\tid,\n\t\t\t\t`--triggers=${triggers}`,\n\t\t\t\t`--address=${address}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should create a new webhook (JSON Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/webhooks', expectedBody).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'webhooks:create',\n\t\t\t\ttype,\n\t\t\t\tid,\n\t\t\t\t`-T=${triggers}`,\n\t\t\t\t`-a=${address}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should create a new webhook (YAML Output)', (context) => {\n\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t});\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi.post('/2.0/webhooks', expectedBody).reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'webhooks:create',\n\t\t\t\ttype,\n\t\t\t\tid,\n\t\t\t\t`--triggers=${triggers}`,\n\t\t\t\t`--address=${address}`,\n\t\t\t\t'--id-only',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it('should create a new webhook (ID Output)', (context) => {\n\t\t\t\tassert.equal(\n\t\t\t\t\tcontext.stdout,\n\t\t\t\t\t`${JSON.parse(fixture).id}${os.EOL}`\n\t\t\t\t);\n\t\t\t});\n\t});\n\n\tdescribe('webhooks:update', function () {\n\t\tlet webhookId = '1234',\n\t\t\ttriggers = 'FILE.DOWNLOADED,FILE.UPLOADED',\n\t\t\taddress = 'https://dev.name/actions/file_changed',\n\t\t\tfixture = getFixture('webhooks/put_webhooks_id'),\n\t\t\tyamlOutput = getFixture('output/webhooks_update_yaml.txt');\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/webhooks/${webhookId}`, {\n\t\t\t\t\ttriggers: triggers.split(','),\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'webhooks:update',\n\t\t\t\twebhookId,\n\t\t\t\t`--triggers=${triggers}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a webhook with triggers flag passed (JSON Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/webhooks/${webhookId}`, {\n\t\t\t\t\ttriggers: triggers.split(','),\n\t\t\t\t})\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'webhooks:update',\n\t\t\t\twebhookId,\n\t\t\t\t`--triggers=${triggers}`,\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a webhook with triggers flag passed (YAML Output)',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, yamlOutput);\n\t\t\t\t}\n\t\t\t);\n\n\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\tapi\n\t\t\t\t.put(`/2.0/webhooks/${webhookId}`, { address })\n\t\t\t\t.reply(200, fixture)\n\t\t)\n\t\t\t.stdout()\n\t\t\t.command([\n\t\t\t\t'webhooks:update',\n\t\t\t\twebhookId,\n\t\t\t\t`--address=${address}`,\n\t\t\t\t'--json',\n\t\t\t\t'--token=test',\n\t\t\t])\n\t\t\t.it(\n\t\t\t\t'should update a webhook with address flag passed',\n\t\t\t\t(context) => {\n\t\t\t\t\tassert.equal(context.stdout, fixture);\n\t\t\t\t}\n\t\t\t);\n\t});\n});\n"
  },
  {
    "path": "test/fixtures/ai/post_ai_ask_response.json",
    "content": "{\n    \"answer\": \"The document is currently in review and awaiting approval.\",\n    \"createdAt\": {\n        \"value\": \"2024-07-09T11:29:46.835Z\"\n    },\n    \"completionReason\": \"done\",\n    \"aiAgentInfo\": {\n        \"models\": [\n            {\n                \"name\": \"google__gemini_2_0_flash_001\",\n                \"provider\": \"google\"\n            }\n        ],\n        \"processor\": \"basic_text\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/ai/post_ai_ask_response_yaml.txt",
    "content": "Answer: The document is currently in review and awaiting approval.\nCreated At:\n    Value: '2024-07-09T11:29:46.835Z'\nCompletion Reason: done\nAi Agent Info:\n    Models:\n        -\n            Name: google__gemini_2_0_flash_001\n            Provider: google\n    Processor: basic_text\n"
  },
  {
    "path": "test/fixtures/ai/post_ai_extract_response.json",
    "content": "{\n    \"answer\": \"{\\\"firstName\\\": \\\"John\\\", \\\"lastName\\\": \\\"Doe\\\", \\\"location\\\": \\\"San Francisco\\\", \\\"yearOfBirth\\\": \\\"1990\\\", \\\"company\\\": \\\"Box\\\"}\",\n    \"createdAt\": {\n        \"value\": \"2025-05-02T14:51:30.567Z\"\n    },\n    \"completionReason\": \"done\",\n    \"aiAgentInfo\": {\n        \"models\": [\n            {\n                \"name\": \"google__gemini_2_0_flash_001\",\n                \"provider\": \"google\"\n            }\n        ],\n        \"processor\": \"basic_text\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/ai/post_ai_extract_response_yaml.txt",
    "content": "Answer: >-\n    {\"firstName\": \"John\", \"lastName\": \"Doe\", \"location\": \"San Francisco\",\n    \"yearOfBirth\": \"1990\", \"company\": \"Box\"}\nCreated At:\n    Value: '2025-05-02T14:51:30.567Z'\nCompletion Reason: done\nAi Agent Info:\n    Models:\n        -\n            Name: google__gemini_2_0_flash_001\n            Provider: google\n    Processor: basic_text\n"
  },
  {
    "path": "test/fixtures/ai/post_ai_extract_structured_response.json",
    "content": "{\n    \"answer\": {\n        \"firstName\": \"John\",\n        \"lastName\": \"Doe\"\n    },\n    \"created_at\": \"2025-04-29T07:25:24.366-07:00\",\n    \"completion_reason\": \"done\",\n    \"ai_agent_info\": {\n        \"models\": [\n            {\n                \"name\": \"google__gemini_2_0_flash_001\",\n                \"provider\": \"google\"\n            }\n        ],\n        \"processor\": \"basic_text\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/ai/post_ai_extract_structured_response_yaml.txt",
    "content": "Answer:\n    First Name: John\n    Last Name: Doe\nCreated At: '2025-04-29T07:25:24.366-07:00'\nCompletion Reason: done\nAi Agent Info:\n    Models:\n        -\n            Name: google__gemini_2_0_flash_001\n            Provider: google\n    Processor: basic_text\n"
  },
  {
    "path": "test/fixtures/ai/post_ai_text_gen_response.json",
    "content": "{\n    \"answer\": \"The document is currently in review and awaiting approval.\",\n    \"created_at\": \"2024-07-09T11:29:46.835Z\",\n    \"completion_reason\": \"done\"\n}\n"
  },
  {
    "path": "test/fixtures/ai/post_ai_text_gen_response_yaml.txt",
    "content": "Answer: The document is currently in review and awaiting approval.\nCreated At: '2024-07-09T11:29:46.835Z'\nCompletion Reason: done\n"
  },
  {
    "path": "test/fixtures/bulk/bulk_files_tasks_list_input.json",
    "content": "[\n    {\n        \"id\": \"123\"\n    },\n    {\n        \"id\": \"456\"\n    },\n    {\n        \"id\": \"789\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/bulk/folder_collab_input.csv",
    "content": "id,login\n11111,mario@example.com\n22222,wario@example.com\n33333,peach@example.com"
  },
  {
    "path": "test/fixtures/bulk/folder_collab_input_no_header.csv",
    "content": "11111,mario@example.com"
  },
  {
    "path": "test/fixtures/bulk/folder_collab_input_no_header_multiple.csv",
    "content": "11111,mario@example.com\n22222,wario@example.com\n33333,peach@example.com"
  },
  {
    "path": "test/fixtures/bulk/input.csv",
    "content": "itemID,itemType,can-view-path,login\n11111,folder,TRUE,\n22222,folder,,roger.federer@example.com\n,file,FALSE,dominic.toretto@example.com"
  },
  {
    "path": "test/fixtures/bulk/input.txt",
    "content": "'foo'"
  },
  {
    "path": "test/fixtures/bulk/input_array.json",
    "content": "[\n    {\n        \"itemID\": \"11111\",\n        \"itemType\": \"folder\",\n        \"can-view-path\": true\n    },\n    {\n        \"itemid\": \"22222\",\n        \"itemtype\": \"folder\",\n        \"login\": \"roger.federer@example.com\"\n    },\n    {\n        \"itemtype\": \"file\",\n        \"can-view-path\": false,\n        \"login\": \"dominic.toretto@example.com\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/bulk/input_asuser_flag_multiple.csv",
    "content": "itemID,itemType,canViewPath,as-user\n11111,folder,true,12345\n11111,folder,true,"
  },
  {
    "path": "test/fixtures/bulk/input_asuser_flag_single.csv",
    "content": "itemID,itemType,canViewPath,as-user\n11111,folder,true,12345"
  },
  {
    "path": "test/fixtures/bulk/input_bogus_keys.csv",
    "content": "itemID,itemType,canViewPath,foo,bar,baz_0,baz_1\n11111,folder,true,fooValue,barValue,bazValue1,bazValue2"
  },
  {
    "path": "test/fixtures/bulk/input_bogus_keys.json",
    "content": "[\n    {\n        \"itemID\": \"11111\",\n        \"itemType\": \"folder\",\n        \"can_view_path\": true,\n        \"foo\": \"bar\",\n        \"baz\": [\n            \"quux\"\n        ],\n        \"nested\": {\n            \"blah\": \"ugh\"\n        }\n    }\n]"
  },
  {
    "path": "test/fixtures/bulk/input_entries.json",
    "content": "{\n\t\"entries\": [\n\t\t{\n\t\t\t\"itemID\": \"11111\",\n\t\t\t\"itemType\": \"folder\",\n\t\t\t\"can-view-path\": true\n\t\t},\n\t\t{\n\t\t\t\"itemid\": \"22222\",\n\t\t\t\"itemtype\": \"folder\",\n\t\t\t\"login\": \"roger.federer@example.com\"\n\t\t},\n\t\t{\n\t\t\t\"itemtype\": \"file\",\n\t\t\t\"can-view-path\": false,\n\t\t\t\"login\": \"dominic.toretto@example.com\"\n\t\t}\n\t]\n}"
  },
  {
    "path": "test/fixtures/bulk/input_groups_terminate_sessions.csv",
    "content": "group-ids\n111\n222"
  },
  {
    "path": "test/fixtures/bulk/input_invalid.json",
    "content": "{\n    // JSON doesn't allow comments, so this line is invalid!\n    \"foo\": \"bar\",\n    \"baz\": \"quux\"\n}\n"
  },
  {
    "path": "test/fixtures/bulk/input_key_casing.csv",
    "content": "Item_Id,Item_Type,canViewPath,LogiN\n11111,folder,TRUE,\n22222,folder,,roger.federer@example.com\n,file,FALSE,dominic.toretto@example.com"
  },
  {
    "path": "test/fixtures/bulk/input_key_casing.json",
    "content": "[\n    {\n        \"itemID\": \"11111\",\n        \"itemType\": \"folder\",\n        \"canViewPath\": true\n    },\n    {\n        \"itemid\": \"22222\",\n        \"itemtype\": \"folder\",\n        \"login\": \"roger.federer@example.com\"\n    },\n    {\n        \"ITEM_TYPE\": \"file\",\n        \"CAN_VIEW_PATH\": false,\n        \"LOGIN\": \"dominic.toretto@example.com\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/bulk/input_manual_request_folder_lock.csv",
    "content": "RESOURCE,method\nhttps://api.box.com/2.0/folder_locks,POST"
  },
  {
    "path": "test/fixtures/bulk/input_metadata_update.csv",
    "content": "add_0,test,add_1,copy\nfoo=bar,\"baz=[stuff,nonsense]\",/anotherOne=#-2.5,sou\\/rce[0]>destination\n"
  },
  {
    "path": "test/fixtures/bulk/input_metadata_update.json",
    "content": "[\n    {\n        \"ops\": [\n            {\n                \"add\": \"foo=bar\"\n            },\n            {\n                \"test\": \"baz=[stuff,nonsense]\"\n            },\n            {\n                \"add\": \"/anotherOne=#-2.5\"\n            },\n            {\n                \"copy\": \"sou\\\\/rce[0]>destination\"\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/fixtures/bulk/input_multiple_same_flag.csv",
    "content": "mdfilter_1,mdfilter_2\nenterprise.myTemplate.name=Matt,enterprise.myTemplate.age=30f"
  },
  {
    "path": "test/fixtures/bulk/input_multiple_same_flag.json",
    "content": "[\n    {\n        \"mdfilter\": [\n            \"enterprise.myTemplate.name=Matt\",\n            \"enterprise.myTemplate.age=30f\"\n        ]\n    }\n]"
  },
  {
    "path": "test/fixtures/bulk/input_nested_keys.json",
    "content": "[\n    {\n        \"item\": {\n            \"id\": \"11111\",\n            \"type\": \"folder\"\n        },\n        \"can-view-path\": true\n    }\n]\n"
  },
  {
    "path": "test/fixtures/bulk/input_object.json",
    "content": "{\n    \"itemid\": \"11111\",\n    \"itemtype\": \"folder\",\n    \"can-view-path\": true\n}\n"
  },
  {
    "path": "test/fixtures/bulk/input_sign_request_create.csv",
    "content": "signer,source-files,parent-folder\n\"email=userA@email.com,role=approver\",\"2468135790,2468135791\",\"1357902468\"\n"
  },
  {
    "path": "test/fixtures/bulk/input_users_terminate_sessions.csv",
    "content": "user-logins,user-ids\nuser1@example.com,111\nuser2@example.com,222"
  },
  {
    "path": "test/fixtures/bulk/input_with_empty_string.csv",
    "content": "id,name,description\n11111,dat.dat,\n22222,doc.docx,\"\"\n"
  },
  {
    "path": "test/fixtures/bulk/post_collaborations_csv.csv",
    "content": "type,id,created_by.type,created_by.id,created_by.name,created_by.login,created_at,modified_at,status,accessible_by.type,accessible_by.id,accessible_by.name,accessible_by.login,role,acknowledged_at,item.type,item.id,item.sequence_id,item.etag,item.name\ncollaboration,1234567890,user,9753108642,Inviting User,invites@example.com,2016-11-16T21:33:31-08:00,2016-11-16T21:33:31-08:00,accepted,user,987654321,Steve Jobs,steve.jobs@example.com,previewer,2016-11-16T21:33:31-08:00,file,11111,0,0,Collaborated File\ncollaboration,1234567891,user,9753108642,Inviting User,invites@example.com,2016-11-16T21:33:31-08:00,2016-11-16T21:33:31-08:00,accepted,user,987654322,Roger Federer,roger.federer@example.com,previewer,2016-11-16T21:33:31-08:00,file,22222,0,0,Collaborated File\ncollaboration,1234567892,user,9753108642,Inviting User,invites@example.com,2016-11-16T21:33:31-08:00,2016-11-16T21:33:31-08:00,accepted,user,987654323,Dominic Toretto,dominic.toretto@example.com,previewer,2016-11-16T21:33:31-08:00,file,33333,0,0,Collaborated File\n"
  },
  {
    "path": "test/fixtures/bulk/post_collaborations_table.txt",
    "content": "----- Collaboration 1234567890 -----\nType: collaboration\nID: '1234567890'\nCreated By:\n    Type: user\n    ID: '9753108642'\n    Name: Inviting User\n    Login: invites@example.com\nCreated At: '2016-11-16T21:33:31-08:00'\nModified At: '2016-11-16T21:33:31-08:00'\nExpires At: null\nStatus: accepted\nAccessible By:\n    Type: user\n    ID: '987654321'\n    Name: Steve Jobs\n    Login: steve.jobs@example.com\nRole: previewer\nAcknowledged At: '2016-11-16T21:33:31-08:00'\nItem:\n    Type: file\n    ID: '11111'\n    Sequence ID: '0'\n    ETag: '0'\n    Name: Collaborated File\n\n----- Collaboration 1234567891 -----\nType: collaboration\nID: '1234567891'\nCreated By:\n    Type: user\n    ID: '9753108642'\n    Name: Inviting User\n    Login: invites@example.com\nCreated At: '2016-11-16T21:33:31-08:00'\nModified At: '2016-11-16T21:33:31-08:00'\nExpires At: null\nStatus: accepted\nAccessible By:\n    Type: user\n    ID: '987654322'\n    Name: Roger Federer\n    Login: roger.federer@example.com\nRole: previewer\nAcknowledged At: '2016-11-16T21:33:31-08:00'\nItem:\n    Type: file\n    ID: '22222'\n    Sequence ID: '0'\n    ETag: '0'\n    Name: Collaborated File\n\n----- Collaboration 1234567892 -----\nType: collaboration\nID: '1234567892'\nCreated By:\n    Type: user\n    ID: '9753108642'\n    Name: Inviting User\n    Login: invites@example.com\nCreated At: '2016-11-16T21:33:31-08:00'\nModified At: '2016-11-16T21:33:31-08:00'\nExpires At: null\nStatus: accepted\nAccessible By:\n    Type: user\n    ID: '987654323'\n    Name: Dominic Toretto\n    Login: dominic.toretto@example.com\nRole: previewer\nAcknowledged At: '2016-11-16T21:33:31-08:00'\nItem:\n    Type: file\n    ID: '33333'\n    Sequence ID: '0'\n    ETag: '0'\n    Name: Collaborated File\n"
  },
  {
    "path": "test/fixtures/bulk/post_collaborations_user_1.json",
    "content": "{\n    \"type\": \"collaboration\",\n    \"id\": \"1234567890\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"9753108642\",\n        \"name\": \"Inviting User\",\n        \"login\": \"invites@example.com\"\n    },\n    \"created_at\": \"2016-11-16T21:33:31-08:00\",\n    \"modified_at\": \"2016-11-16T21:33:31-08:00\",\n    \"expires_at\": null,\n    \"status\": \"accepted\",\n    \"accessible_by\": {\n        \"type\": \"user\",\n        \"id\": \"987654321\",\n        \"name\": \"Steve Jobs\",\n        \"login\": \"steve.jobs@example.com\"\n    },\n    \"role\": \"previewer\",\n    \"acknowledged_at\": \"2016-11-16T21:33:31-08:00\",\n    \"item\": {\n        \"type\": \"file\",\n        \"id\": \"11111\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"Collaborated File\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/bulk/post_collaborations_user_2.json",
    "content": "{\n    \"type\": \"collaboration\",\n    \"id\": \"1234567891\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"9753108642\",\n        \"name\": \"Inviting User\",\n        \"login\": \"invites@example.com\"\n    },\n    \"created_at\": \"2016-11-16T21:33:31-08:00\",\n    \"modified_at\": \"2016-11-16T21:33:31-08:00\",\n    \"expires_at\": null,\n    \"status\": \"accepted\",\n    \"accessible_by\": {\n        \"type\": \"user\",\n        \"id\": \"987654322\",\n        \"name\": \"Roger Federer\",\n        \"login\": \"roger.federer@example.com\"\n    },\n    \"role\": \"previewer\",\n    \"acknowledged_at\": \"2016-11-16T21:33:31-08:00\",\n    \"item\": {\n        \"type\": \"file\",\n        \"id\": \"22222\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"Collaborated File\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/bulk/post_collaborations_user_3.json",
    "content": "{\n    \"type\": \"collaboration\",\n    \"id\": \"1234567892\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"9753108642\",\n        \"name\": \"Inviting User\",\n        \"login\": \"invites@example.com\"\n    },\n    \"created_at\": \"2016-11-16T21:33:31-08:00\",\n    \"modified_at\": \"2016-11-16T21:33:31-08:00\",\n    \"expires_at\": null,\n    \"status\": \"accepted\",\n    \"accessible_by\": {\n        \"type\": \"user\",\n        \"id\": \"987654323\",\n        \"name\": \"Dominic Toretto\",\n        \"login\": \"dominic.toretto@example.com\"\n    },\n    \"role\": \"previewer\",\n    \"acknowledged_at\": \"2016-11-16T21:33:31-08:00\",\n    \"item\": {\n        \"type\": \"file\",\n        \"id\": \"33333\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"Collaborated File\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/bulk/post_folders_lock.json",
    "content": "{\n    \"folder\": {\n      \"type\": \"folder\",\n      \"id\": \"123\",\n      \"sequence_id\": \"1\",\n      \"etag\": \"1\",\n      \"name\": \"locked_folder\"\n    },\n    \"id\": \"2648\",\n    \"type\": \"folder_lock\",\n    \"created_by\": {\n      \"id\": \"1111\",\n      \"type\": \"user\"\n    },\n    \"created_at\": \"2019-10-17T18:06:36Z\",\n    \"lock_type\": \"freeze\"\n  }"
  },
  {
    "path": "test/fixtures/bulk/post_sign_requests.json",
    "content": "{\n\t\"is_document_preparation_needed\": false,\n\t\"redirect_url\": null,\n\t\"declined_redirect_url\": null,\n\t\"are_text_signatures_enabled\": true,\n\t\"signature_color\": null,\n\t\"is_phone_verification_required_to_view\": false,\n\t\"email_subject\": null,\n\t\"email_message\": null,\n\t\"are_reminders_enabled\": false,\n\t\"signers\": [\n\t\t{\n\t\t\t\"email\": \"user@email.com\",\n\t\t\t\"role\": \"final_copy_reader\",\n\t\t\t\"is_in_person\": false,\n\t\t\t\"order\": 0,\n\t\t\t\"verification_phone_number\": null,\n\t\t\t\"embed_url_external_user_id\": null,\n\t\t\t\"redirect_url\": null,\n\t\t\t\"declined_redirect_url\": null,\n\t\t\t\"login_required\": false,\n\t\t\t\"has_viewed_document\": false,\n\t\t\t\"signer_decision\": null,\n\t\t\t\"signer_group_id\": null,\n\t\t\t\"inputs\": [],\n\t\t\t\"embed_url\": null,\n\t\t\t\"iframeable_embed_url\": null,\n\t\t\t\"suppress_notifications\": false\n\t\t},\n\t\t{\n\t\t\t\"email\": \"userA@email.com\",\n\t\t\t\"role\": \"approver\",\n\t\t\t\"is_in_person\": false,\n\t\t\t\"order\": 0,\n\t\t\t\"verification_phone_number\": null,\n\t\t\t\"embed_url_external_user_id\": null,\n\t\t\t\"redirect_url\": null,\n\t\t\t\"declined_redirect_url\": null,\n\t\t\t\"login_required\": false,\n\t\t\t\"has_viewed_document\": false,\n\t\t\t\"signer_decision\": null,\n\t\t\t\"signer_group_id\": null,\n\t\t\t\"inputs\": [],\n\t\t\t\"embed_url\": null,\n\t\t\t\"iframeable_embed_url\": null,\n\t\t\t\"suppress_notifications\": false\n\t\t}\n\t],\n\t\"id\": \"ce25caf8-54e5-4860-8006-f9f6886551c5\",\n\t\"prefill_tags\": [],\n\t\"days_valid\": null,\n\t\"prepare_url\": null,\n\t\"source_files\": [\n\t\t{\n\t\t\t\"id\": \"2468135790\",\n\t\t\t\"etag\": \"0\",\n\t\t\t\"type\": \"file\",\n\t\t\t\"sequence_id\": \"0\",\n\t\t\t\"name\": \"report1.xlsx\",\n\t\t\t\"sha1\": \"2150fa7e04d87e776ee8fc04fc098b6d977c0ca5\",\n\t\t\t\"file_version\": {\n\t\t\t\t\"id\": \"1702075180104\",\n\t\t\t\t\"type\": \"file_version\",\n\t\t\t\t\"sha1\": \"2150fa7e04d87e776ee8fc04fc098b6d977c0ca5\"\n\t\t\t}\n\t\t},\n\t\t{\n\t\t\t\"id\": \"2468135791\",\n\t\t\t\"etag\": \"0\",\n\t\t\t\"type\": \"file\",\n\t\t\t\"sequence_id\": \"0\",\n\t\t\t\"name\": \"report2.xlsx\",\n\t\t\t\"sha1\": \"f75575f090598f46fbde405e3ea4424c1e7fd6c8\",\n\t\t\t\"file_version\": {\n\t\t\t\t\"id\": \"1702075180105\",\n\t\t\t\t\"type\": \"file_version\",\n\t\t\t\t\"sha1\": \"f75575f090598f46fbde405e3ea4424c1e7fd6c8\"\n\t\t\t}\n\t\t}\n\t],\n\t\"parent_folder\": {\n\t\t\"id\": \"1357902468\",\n\t\t\"etag\": \"0\",\n\t\t\"type\": \"folder\",\n\t\t\"sequence_id\": \"0\",\n\t\t\"name\": \"myReports\"\n\t},\n\t\"name\": \"sign1\",\n\t\"external_id\": null,\n\t\"type\": \"sign-request\",\n\t\"signing_log\": null,\n\t\"status\": \"converting\",\n\t\"sign_files\": {\n\t\t\"files\": [\n\t\t\t{\n\t\t\t\t\"id\": \"4568135987\",\n\t\t\t\t\"etag\": \"0\",\n\t\t\t\t\"type\": \"file\",\n\t\t\t\t\"sequence_id\": \"0\",\n\t\t\t\t\"name\": \"report1.xlsx\",\n\t\t\t\t\"sha1\": \"2150fa7e04d87e776ee8fc04fc098b6d977c0ca5\",\n\t\t\t\t\"file_version\": {\n\t\t\t\t\t\"id\": \"1702075180104\",\n\t\t\t\t\t\"type\": \"file_version\",\n\t\t\t\t\t\"sha1\": \"2150fa7e04d87e776ee8fc04fc098b6d977c0ca5\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"id\": \"4568135988\",\n\t\t\t\t\"etag\": \"0\",\n\t\t\t\t\"type\": \"file\",\n\t\t\t\t\"sequence_id\": \"0\",\n\t\t\t\t\"name\": \"report2.xlsx\",\n\t\t\t\t\"sha1\": \"f75575f090598f46fbde405e3ea4424c1e7fd6c8\",\n\t\t\t\t\"file_version\": {\n\t\t\t\t\t\"id\": \"1702075180105\",\n\t\t\t\t\t\"type\": \"file_version\",\n\t\t\t\t\t\"sha1\": \"f75575f090598f46fbde405e3ea4424c1e7fd6c8\"\n\t\t\t\t}\n\t\t\t}\n\t\t],\n\t\t\"is_ready_for_download\": true\n\t},\n\t\"auto_expire_at\": null,\n\t\"template_id\": null,\n\t\"external_system_name\": null\n}\n"
  },
  {
    "path": "test/fixtures/bulk/post_terminate_sessions.json",
    "content": "{\n    \"message\": \"Request is successful, please check the admin events for the status of the job\"\n}\n"
  },
  {
    "path": "test/fixtures/bulk/saveTest.txt",
    "content": "foo"
  },
  {
    "path": "test/fixtures/collaboration-allowlist/get_collaboration_whitelist_entries_id.json",
    "content": "{\n    \"type\": \"collaboration_whitelist_entry\",\n    \"id\": \"11111\",\n    \"domain\": \"box.com\",\n    \"direction\": \"both\",\n    \"enterprise\": {\n        \"type\": \"enterprise\",\n        \"id\": \"22222\",\n        \"name\": \"Test Enterprise\"\n    },\n    \"created_at\": \"2018-04-23T21:31:07-07:00\",\n    \"modified_at\": \"2018-04-23T21:31:07-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/collaboration-allowlist/get_collaboration_whitelist_entries_page_1.json",
    "content": "{\n    \"entries\": [\n        {\n            \"type\": \"collaboration_whitelist_entry\",\n            \"id\": \"11111\",\n            \"domain\": \"box.com\",\n            \"direction\": \"both\"\n        }\n    ],\n    \"limit\": 100,\n    \"order\": [\n        {\n            \"by\": \"id\",\n            \"direction\": \"ASC\"\n        }\n    ],\n\t\"next_marker\": \"ZEDFO9\"\n}\n"
  },
  {
    "path": "test/fixtures/collaboration-allowlist/get_collaboration_whitelist_entries_page_2.json",
    "content": "{\n    \"entries\": [\n        {\n            \"type\": \"collaboration_whitelist_entry\",\n            \"id\": \"111112\",\n            \"domain\": \"box.com\",\n            \"direction\": \"both\"\n        }\n    ],\n    \"limit\": 100,\n    \"order\": [\n        {\n            \"by\": \"id\",\n            \"direction\": \"ASC\"\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/collaboration-allowlist/get_collaboration_whitelist_exempt_targets_id.json",
    "content": "{\n    \"type\": \"collaboration_whitelist_exempt_target\",\n    \"id\": \"11111\",\n    \"user\": {\n        \"type\": \"user\",\n        \"id\": \"22222\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"enterprise\": {\n        \"type\": \"enterprise\",\n        \"id\": \"33333\",\n        \"name\": \"Test Enterprise\"\n    },\n    \"created_at\": \"2018-04-23T21:45:12-07:00\",\n    \"modified_at\": \"2018-04-23T21:45:12-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/collaboration-allowlist/get_collaboration_whitelist_exempt_targets_page_1.json",
    "content": "{\n\t\"entries\": [\n\t\t{\n\t\t\t\"type\": \"collaboration_whitelist_exempt_target\",\n\t\t\t\"id\": \"11111\",\n\t\t\t\"user\": {\n\t\t\t\t\"type\": \"user\",\n\t\t\t\t\"id\": \"22222\",\n\t\t\t\t\"name\": \"Test User\",\n\t\t\t\t\"login\": \"testuser@example.com\"\n\t\t\t}\n        }\n    ],\n\t\"limit\": 100,\n\t\"order\": [\n\t\t{\n\t\t\t\"by\": \"id\",\n\t\t\t\"direction\": \"ASC\"\n        }\n    ],\n\t\"next_marker\": \"ZDEH786\"\n}\n"
  },
  {
    "path": "test/fixtures/collaboration-allowlist/get_collaboration_whitelist_exempt_targets_page_2.json",
    "content": "{\n\t\"entries\": [\n\t\t{\n\t\t\t\"type\": \"collaboration_whitelist_exempt_target\",\n\t\t\t\"id\": \"111112\",\n\t\t\t\"user\": {\n\t\t\t\t\"type\": \"user\",\n\t\t\t\t\"id\": \"22222\",\n\t\t\t\t\"name\": \"Test User\",\n\t\t\t\t\"login\": \"testuser@example.com\"\n\t\t\t}\n        }\n    ],\n\t\"limit\": 100,\n\t\"order\": [\n\t\t{\n\t\t\t\"by\": \"id\",\n\t\t\t\"direction\": \"ASC\"\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/collaboration-allowlist/post_collaboration_exempt_targets.json",
    "content": "{\n    \"type\": \"collaboration_whitelist_exempt_target\",\n    \"id\": \"1234\",\n    \"user\": {\n        \"type\": \"user\",\n        \"id\": \"5678\",\n        \"name\": \"example user\",\n        \"login\": \"test@example.com\"\n    },\n    \"enterprise\": {\n        \"type\": \"enterprise\",\n        \"id\": \"12345678\",\n        \"name\": \"Box\"\n    },\n    \"created_at\": \"2017-12-06T16:57:17-08:00\",\n    \"modified_at\": \"2017-12-06T16:57:17-08:00\"\n}\n"
  },
  {
    "path": "test/fixtures/collaboration-allowlist/post_collaboration_whitelists.json",
    "content": "{\n    \"type\": \"collaboration_whitelist_entry\",\n    \"id\": \"1234\",\n    \"domain\": \"test.com\",\n    \"direction\": \"both\",\n    \"enterprise\": {\n        \"type\": \"enterprise\",\n        \"id\": \"12345678\",\n        \"name\": \"Box\"\n    },\n    \"created_at\": \"2017-12-06T15:05:28-08:00\",\n    \"modified_at\": \"2017-12-06T15:05:28-08:00\"\n}\n"
  },
  {
    "path": "test/fixtures/collaborations/get_collaborations_id.json",
    "content": "{\n    \"type\": \"collaboration\",\n    \"id\": \"1234567890\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"123456789\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"aaron@example.com\"\n    },\n    \"created_at\": \"2015-07-09T16:37:27-07:00\",\n    \"modified_at\": \"2016-08-30T14:35:32-07:00\",\n    \"expires_at\": null,\n    \"status\": \"accepted\",\n    \"accessible_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Dylan Smith\",\n        \"login\": \"dylan@example.com\"\n    },\n    \"role\": \"editor\",\n    \"acknowledged_at\": \"2015-07-09T16:37:27-07:00\",\n    \"item\": {\n        \"type\": \"folder\",\n        \"id\": \"3936621105\",\n        \"sequence_id\": \"2\",\n        \"etag\": \"2\",\n        \"name\": \"150630. Recents\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/collaborations/get_collaborations_pending_page_1.json",
    "content": "{\n    \"total_count\": 2,\n    \"entries\": [\n        {\n            \"type\": \"collaboration\",\n            \"id\": \"1234567890\",\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"9087654321\",\n                \"name\": \"Some Other User\",\n                \"login\": \"otheruser@example.com\"\n            },\n            \"created_at\": \"2016-11-16T20:52:34-08:00\",\n            \"modified_at\": \"2016-11-16T20:52:34-08:00\",\n            \"expires_at\": null,\n            \"status\": \"pending\",\n            \"accessible_by\": {\n                \"type\": \"user\",\n                \"id\": \"132467469\",\n                \"name\": \"Current User\",\n                \"login\": \"me@example.com\"\n            },\n            \"role\": \"editor\",\n            \"acknowledged_at\": null,\n            \"item\": null\n        }\n    ],\n    \"limit\": 1,\n    \"offset\": 0\n}\n"
  },
  {
    "path": "test/fixtures/collaborations/get_collaborations_pending_page_2.json",
    "content": "{\n    \"total_count\": 2,\n    \"entries\": [\n        {\n            \"type\": \"collaboration\",\n            \"id\": \"1234567890\",\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"9087654320\",\n                \"name\": \"Some Other User\",\n                \"login\": \"otheruser@example.com\"\n            },\n            \"created_at\": \"2016-11-16T20:52:34-08:00\",\n            \"modified_at\": \"2016-11-16T20:52:34-08:00\",\n            \"expires_at\": null,\n            \"status\": \"pending\",\n            \"accessible_by\": {\n                \"type\": \"user\",\n                \"id\": \"132467469\",\n                \"name\": \"Current User\",\n                \"login\": \"me@example.com\"\n            },\n            \"role\": \"editor\",\n            \"acknowledged_at\": null,\n            \"item\": null\n        }\n    ],\n    \"limit\": 1,\n    \"offset\": 1\n}\n"
  },
  {
    "path": "test/fixtures/collaborations/get_groups_id_collaborations_page_1.json",
    "content": "{\n    \"total_count\": 2,\n    \"entries\": [\n        {\n            \"type\": \"collaboration\",\n            \"id\": \"123456\",\n            \"created_by\": null,\n            \"created_at\": \"2016-11-16T21:48:44-08:00\",\n            \"modified_at\": \"2016-11-16T21:48:44-08:00\",\n            \"expires_at\": null,\n            \"status\": \"accepted\",\n            \"accessible_by\": {\n                \"type\": \"group\",\n                \"id\": \"11111\",\n                \"name\": \"Remote Employees\",\n                \"group_type\": \"managed_group\"\n            },\n            \"role\": \"editor\",\n            \"acknowledged_at\": \"2016-11-16T21:48:44-08:00\",\n            \"item\": {\n                \"type\": \"folder\",\n                \"id\": \"22222\",\n                \"sequence_id\": \"1\",\n                \"etag\": \"1\",\n                \"name\": \"Collab Folder\"\n            }\n        }\n    ],\n    \"offset\": 0,\n    \"limit\": 1\n}"
  },
  {
    "path": "test/fixtures/collaborations/get_groups_id_collaborations_page_2.json",
    "content": "{\n    \"total_count\": 2,\n    \"entries\": [\n        {\n            \"type\": \"collaboration\",\n            \"id\": \"1234567\",\n            \"created_by\": null,\n            \"created_at\": \"2016-11-16T21:48:44-08:00\",\n            \"modified_at\": \"2016-11-16T21:48:44-08:00\",\n            \"expires_at\": null,\n            \"status\": \"accepted\",\n            \"accessible_by\": {\n                \"type\": \"group\",\n                \"id\": \"11111\",\n                \"name\": \"Remote Employees\",\n                \"group_type\": \"managed_group\"\n            },\n            \"role\": \"editor\",\n            \"acknowledged_at\": \"2016-11-16T21:48:44-08:00\",\n            \"item\": {\n                \"type\": \"folder\",\n                \"id\": \"22222\",\n                \"sequence_id\": \"1\",\n                \"etag\": \"1\",\n                \"name\": \"Collab Folder\"\n            }\n        }\n    ],\n    \"offset\": 1,\n    \"limit\": 1\n}"
  },
  {
    "path": "test/fixtures/collaborations/post_collaborations_user.json",
    "content": "{\n    \"type\": \"collaboration\",\n    \"id\": \"1234567890\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"9753108642\",\n        \"name\": \"Inviting User\",\n        \"login\": \"invites@example.com\"\n    },\n    \"created_at\": \"2016-11-16T21:33:31-08:00\",\n    \"modified_at\": \"2016-11-16T21:33:31-08:00\",\n    \"expires_at\": null,\n    \"status\": \"accepted\",\n    \"accessible_by\": {\n        \"type\": \"user\",\n        \"id\": \"987654321\",\n        \"name\": \"My New Friend\",\n        \"login\": \"newfriend@example.com\"\n    },\n    \"role\": \"previewer\",\n    \"acknowledged_at\": \"2016-11-16T21:33:31-08:00\",\n    \"item\": {\n        \"type\": \"file\",\n        \"id\": \"1234567890\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"Collaborated File\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/collaborations/put_collaborations_id.json",
    "content": "{\n    \"type\": \"collaboration\",\n    \"id\": \"1234567890\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"834098476\",\n        \"name\": \"Inviting User\",\n        \"login\": \"inviter@example.com\"\n    },\n    \"created_at\": \"2015-11-03T18:36:37-08:00\",\n    \"modified_at\": \"2016-11-16T21:01:19-08:00\",\n    \"expires_at\": null,\n    \"status\": \"accepted\",\n    \"accessible_by\": {\n        \"type\": \"user\",\n        \"id\": \"6789234576\",\n        \"name\": \"Collaborated User\",\n        \"login\": \"collaborator@example.com\"\n    },\n    \"role\": \"viewer\",\n    \"acknowledged_at\": \"2015-11-03T18:36:37-08:00\",\n    \"item\": {\n        \"type\": \"folder\",\n        \"id\": \"9087654321\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"name\": \"Collaborated Folder\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/collections/get_collections.json",
    "content": "{\n    \"total_count\": 1,\n    \"entries\": [\n        {\n            \"type\": \"collection\",\n            \"id\": \"123456789\",\n            \"name\": \"Favorites\",\n            \"collection_type\": \"favorites\"\n        }\n    ],\n    \"limit\": 100,\n    \"offset\": 0\n}\n"
  },
  {
    "path": "test/fixtures/collections/get_collections_id_items_page_1.json",
    "content": "{\n\t\"total_count\": 4,\n\t\"entries\": [{\n\t\t\t\"type\": \"folder\",\n\t\t\t\"id\": \"192429928\",\n\t\t\t\"sequence_id\": \"1\",\n\t\t\t\"etag\": \"1\",\n\t\t\t\"name\": \"Stephen Curry Three Pointers\"\n        },\n\t\t{\n\t\t\t\"type\": \"file\",\n\t\t\t\"id\": \"818853862\",\n\t\t\t\"sequence_id\": \"0\",\n\t\t\t\"etag\": \"0\",\n\t\t\t\"name\": \"Warriors.jpg\"\n        }],\n\t\"limit\": 2,\n\t\"offset\": 0\n}\n"
  },
  {
    "path": "test/fixtures/collections/get_collections_id_items_page_2.json",
    "content": "{\n\t\"total_count\": 4,\n\t\"entries\": [{\n\t\t\t\"type\": \"folder\",\n\t\t\t\"id\": \"192429928\",\n\t\t\t\"sequence_id\": \"1\",\n\t\t\t\"etag\": \"1\",\n\t\t\t\"name\": \"Roger Federer Grandslams\"\n        },\n\t\t{\n\t\t\t\"type\": \"file\",\n\t\t\t\"id\": \"818853862\",\n\t\t\t\"sequence_id\": \"0\",\n\t\t\t\"etag\": \"0\",\n\t\t\t\"name\": \"Basel.jpg\"\n        }],\n\t\"limit\": 2,\n\t\"offset\": 2\n}\n"
  },
  {
    "path": "test/fixtures/collections/get_files_id.json",
    "content": "{\n\t\"type\": \"file\",\n\t\"id\": \"1234567890\",\n\t\"file_version\": {\n\t\t\"type\": \"file_version\",\n\t\t\"id\": \"11223344556677\",\n\t\t\"sha1\": \"97b3dbba6eab7ad0f058240744c8636b7c7bea93\"\n\t},\n\t\"sequence_id\": \"1\",\n\t\"etag\": \"1\",\n\t\"sha1\": \"97b3dbba6eab7ad0f058240744c8636b7c7bea93\",\n\t\"name\": \"test_file_download.txt\",\n\t\"description\": \"\",\n\t\"size\": 106833,\n\t\"path_collection\": {\n\t\t\"total_count\": 2,\n\t\t\"entries\": [\n\t\t\t{\n\t\t\t\t\"type\": \"folder\",\n\t\t\t\t\"id\": \"0\",\n\t\t\t\t\"sequence_id\": null,\n\t\t\t\t\"etag\": null,\n\t\t\t\t\"name\": \"All Files\"\n            },\n\t\t\t{\n\t\t\t\t\"type\": \"folder\",\n\t\t\t\t\"id\": \"987654321\",\n\t\t\t\t\"sequence_id\": \"0\",\n\t\t\t\t\"etag\": \"0\",\n\t\t\t\t\"name\": \"Collaborated Folder\"\n            }\n        ]\n\t},\n\t\"created_at\": \"2016-11-16T22:01:44-08:00\",\n\t\"modified_at\": \"2016-11-16T22:01:51-08:00\",\n\t\"trashed_at\": null,\n\t\"purged_at\": null,\n\t\"content_created_at\": \"2016-10-29T18:33:50-07:00\",\n\t\"content_modified_at\": \"2016-10-29T18:33:50-07:00\",\n\t\"created_by\": {\n\t\t\"type\": \"user\",\n\t\t\"id\": \"1357924680\",\n\t\t\"name\": \"Owner\",\n\t\t\"login\": \"owner@example.com\"\n\t},\n\t\"modified_by\": {\n\t\t\"type\": \"user\",\n\t\t\"id\": \"1357924680\",\n\t\t\"name\": \"Owner\",\n\t\t\"login\": \"owner@example.com\"\n\t},\n\t\"owned_by\": {\n\t\t\"type\": \"user\",\n\t\t\"id\": \"1357924680\",\n\t\t\"name\": \"Owner\",\n\t\t\"login\": \"owner@example.com\"\n\t},\n\t\"shared_link\": null,\n\t\"parent\": {\n\t\t\"type\": \"folder\",\n\t\t\"id\": \"987654321\",\n\t\t\"sequence_id\": \"0\",\n\t\t\"etag\": \"0\",\n\t\t\"name\": \"Collaborated Folder\"\n\t},\n\t\"item_status\": \"active\",\n\t\"collections\": [{ \"id\": \"1234567890\" }]\n}\n"
  },
  {
    "path": "test/fixtures/collections/put_files_id.json",
    "content": "{\n    \"type\": \"file\",\n    \"id\": \"1234567890\",\n    \"file_version\": {\n        \"type\": \"file_version\",\n        \"id\": \"11223344556677\",\n        \"sha1\": \"97b3dbba6eab7ad0f058240744c8636b7c7bea93\"\n    },\n    \"sequence_id\": \"1\",\n    \"etag\": \"1\",\n    \"sha1\": \"97b3dbba6eab7ad0f058240744c8636b7c7bea93\",\n    \"name\": \"test_file_download.txt\",\n    \"description\": \"\",\n    \"size\": 106833,\n    \"path_collection\": {\n        \"total_count\": 2,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"987654321\",\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"name\": \"Collaborated Folder\"\n            }\n        ]\n    },\n    \"created_at\": \"2016-11-16T22:01:44-08:00\",\n    \"modified_at\": \"2016-11-16T22:01:51-08:00\",\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": \"2016-10-29T18:33:50-07:00\",\n    \"content_modified_at\": \"2016-10-29T18:33:50-07:00\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"shared_link\": null,\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"987654321\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"Collaborated Folder\"\n    },\n    \"item_status\": \"active\",\n    \"collections\": []\n}\n"
  },
  {
    "path": "test/fixtures/comments/get_comments_id.json",
    "content": "{\n    \"type\": \"comment\",\n    \"id\": \"123456789\",\n    \"is_reply_comment\": false,\n    \"message\": \"Looks good!\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"9078563412\",\n        \"name\": \"Commenting User\",\n        \"login\": \"comments@example.com\"\n    },\n    \"created_at\": \"2016-11-16T22:03:56-08:00\",\n    \"item\": {\n        \"id\": \"987654321\",\n        \"type\": \"file\"\n    },\n    \"modified_at\": \"2016-11-16T22:03:56-08:00\"\n}\n"
  },
  {
    "path": "test/fixtures/comments/get_files_id_comments_page_1.json",
    "content": "{\n    \"total_count\": 4,\n    \"offset\": 0,\n    \"limit\": 2,\n    \"entries\": [\n        {\n            \"type\": \"comment\",\n            \"id\": \"111111\",\n            \"is_reply_comment\": false,\n            \"message\": \"Hello Nadal\",\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"274664201\",\n                \"name\": \"Roger Federer\",\n                \"login\": \"roger.federer@example.com\"\n            },\n            \"created_at\": \"2018-06-06T13:18:08-07:00\"\n        },\n        {\n            \"type\": \"comment\",\n            \"id\": \"222222\",\n            \"is_reply_comment\": false,\n            \"message\": \"Hello Roger\",\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"274664201\",\n                \"name\": \"Rafa Nadal\",\n                \"login\": \"rafa.nadal@example.com\"\n            },\n            \"created_at\": \"2018-06-06T13:18:22-07:00\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/comments/get_files_id_comments_page_2.json",
    "content": "{\n    \"total_count\": 4,\n    \"offset\": 2,\n    \"limit\": 2,\n    \"entries\": [\n        {\n            \"type\": \"comment\",\n            \"id\": \"1111111\",\n            \"is_reply_comment\": false,\n            \"message\": \"Hello Nadal\",\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"274664201\",\n                \"name\": \"Roger Federer\",\n                \"login\": \"roger.federer@example.com\"\n            },\n            \"created_at\": \"2018-06-06T13:18:08-07:00\"\n        },\n        {\n            \"type\": \"comment\",\n            \"id\": \"2222222\",\n            \"is_reply_comment\": false,\n            \"message\": \"Hello Roger\",\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"274664201\",\n                \"name\": \"Rafa Nadal\",\n                \"login\": \"rafa.nadal@example.com\"\n            },\n            \"created_at\": \"2018-06-06T13:18:22-07:00\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/comments/post_comments.json",
    "content": "{\n    \"type\": \"comment\",\n    \"id\": \"9988776655\",\n    \"is_reply_comment\": false,\n    \"message\": \"Other User Looks good!\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"123456789\",\n        \"name\": \"Matt Willer\",\n        \"login\": \"matt.r.willer+boxadmin@gmail.com\"\n    },\n    \"created_at\": \"2016-11-16T22:08:08-08:00\",\n    \"item\": {\n        \"id\": \"987654321\",\n        \"type\": \"file\"\n    },\n    \"modified_at\": \"2016-11-16T22:08:08-08:00\"\n}\n"
  },
  {
    "path": "test/fixtures/comments/post_comments_reply.json",
    "content": "{\n    \"type\": \"comment\",\n    \"id\": \"191969\",\n    \"is_reply_comment\": true,\n    \"message\": \"These tigers are cool!\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"17738362\",\n        \"name\": \"sean rose\",\n        \"login\": \"sean@example.com\"\n    },\n    \"created_at\": \"2012-12-12T11:25:01-08:00\",\n    \"item\": {\n        \"id\": \"5000948880\",\n        \"type\": \"comment\"\n    },\n    \"modified_at\": \"2012-12-12T11:25:01-08:00\"\n}\n"
  },
  {
    "path": "test/fixtures/comments/put_comments_id.json",
    "content": "{\n    \"type\": \"comment\",\n    \"id\": \"123456789\",\n    \"is_reply_comment\": false,\n    \"message\": \"Looks great!\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"9078563412\",\n        \"name\": \"Commenting User\",\n        \"login\": \"comments@example.com\"\n    },\n    \"created_at\": \"2016-11-16T22:03:56-08:00\",\n    \"item\": {\n        \"id\": \"987654321\",\n        \"type\": \"file\"\n    },\n    \"modified_at\": \"2016-11-16T22:03:56-08:00\"\n}\n"
  },
  {
    "path": "test/fixtures/device-pins/get_device_pinners_id.json",
    "content": "{\n    \"type\": \"device_pinner\",\n    \"id\": \"123456789\",\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"987654321\",\n        \"name\": \"Device User\",\n        \"login\": \"iphone@example.com\"\n    },\n    \"product_name\": \"iPhone\",\n    \"created_at\": \"2016-11-16T19:05:05-08:00\",\n    \"modified_at\": \"2016-11-16T19:05:05-08:00\"\n}\n"
  },
  {
    "path": "test/fixtures/device-pins/get_device_pinners_page_1.json",
    "content": "{\n  \"next_marker\": \"ZDEF67\",  \n\t\"entries\": [\n        {\n            \"type\": \"device_pinner\",\n            \"id\": \"788804\",\n            \"owned_by\": {\n                \"type\": \"user\",\n                \"id\": \"222276603\",\n                \"name\": \"Ted Blosser\",\n                \"login\": \"ted+boxworks2@example.com\"\n            },\n            \"product_name\": \"iPad\"\n        },\n\n        {\n            \"type\": \"device_pinner\",\n            \"id\": \"1003086\",\n            \"owned_by\": {\n                \"type\": \"user\",\n                \"id\": \"222276603\",\n                \"name\": \"Ted Blosser\",\n                \"login\": \"ted+boxworks2@example.com\"\n            },\n            \"product_name\": \"iPhone\"\n        }\n    ],\n    \"limit\": 100,\n    \"order\": [\n        {\n            \"by\": \"id\",\n            \"direction\": \"ASC\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/device-pins/get_device_pinners_page_2.json",
    "content": "{\n\t\"entries\": [\n\t\t{\n\t\t\t\"type\": \"device_pinner\",\n\t\t\t\"id\": \"788803\",\n\t\t\t\"owned_by\": {\n\t\t\t\t\"type\": \"user\",\n\t\t\t\t\"id\": \"222276603\",\n\t\t\t\t\"name\": \"Ted Blosser\",\n\t\t\t\t\"login\": \"ted+boxworks2@example.com\"\n\t\t\t},\n\t\t\t\"product_name\": \"iPad\"\n        },\n\n\t\t{\n\t\t\t\"type\": \"device_pinner\",\n\t\t\t\"id\": \"1003082\",\n\t\t\t\"owned_by\": {\n\t\t\t\t\"type\": \"user\",\n\t\t\t\t\"id\": \"222276603\",\n\t\t\t\t\"name\": \"Ted Blosser\",\n\t\t\t\t\"login\": \"ted+boxworks2@example.com\"\n\t\t\t},\n\t\t\t\"product_name\": \"iPhone\"\n        }\n    ],\n\t\"limit\": 100,\n\t\"order\": [\n\t\t{\n\t\t\t\"by\": \"id\",\n\t\t\t\"direction\": \"ASC\"\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/device-pins/get_users_me.json",
    "content": "{\n    \"type\": \"user\",\n    \"id\": \"1234\",\n    \"enterprise\": {\n        \"type\": \"enterprise\",\n        \"id\": \"123456\",\n        \"name\": \"Box\"\n    }\n}"
  },
  {
    "path": "test/fixtures/events/get_events.json",
    "content": "{\n    \"chunk_size\": 2,\n    \"next_stream_position\": \"1152922976252290886\",\n    \"entries\": [\n        {\n            \"source\": {\n                \"type\": \"user\",\n                \"id\": \"222853849\",\n                \"name\": \"Nick Lee\",\n                \"login\": \"nlee+demo4@example.com\"\n            },\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"222853849\",\n                \"name\": \"sean rose\",\n                \"login\": \"sean+awesome@example.com\"\n            },\n            \"created_at\": \"2015-12-02T09:41:31-08:00\",\n            \"event_id\": \"b9a2393a-20cf-4307-90f5-004110dec209\",\n            \"event_type\": \"ADD_LOGIN_ACTIVITY_DEVICE\",\n            \"ip_address\": \"Unknown IP\",\n            \"type\": \"event\",\n            \"session_id\": null,\n            \"additional_details\": null\n        },\n        {\n            \"source\": {\n                \"type\": \"user\",\n                \"id\": \"222853849\",\n                \"name\": \"sean rose\",\n                \"login\": \"sean+awesome@example.com\"\n            },\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"222853849\",\n                \"name\": \"Nick Lee\",\n                \"login\": \"nlee+demo4@example.com\"\n            },\n            \"created_at\": \"2015-12-02T09:41:31-08:00\",\n            \"event_id\": \"1a4ade15-b1ff-4cc3-89a8-955e1522557c\",\n            \"event_type\": \"LOGIN\",\n            \"ip_address\": \"Unknown IP\",\n            \"type\": \"event\",\n            \"session_id\": null,\n            \"additional_details\": null\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/events/get_events_end.json",
    "content": "{\n    \"chunk_size\": 0,\n    \"next_stream_position\": \"2263033087363301997\",\n    \"entries\": []\n}\n"
  },
  {
    "path": "test/fixtures/events/get_events_second_page.json",
    "content": "{\n    \"chunk_size\": 2,\n    \"next_stream_position\": \"2263033087363301997\",\n    \"entries\": [\n        {\n            \"source\": {\n                \"type\": \"user\",\n                \"id\": \"11111\",\n                \"name\": \"Example User\",\n                \"login\": \"user@example.com\"\n            },\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"22222\",\n                \"name\": \"Example User 2\",\n                \"login\": \"user2@example.com\"\n            },\n            \"created_at\": \"2015-12-02T09:41:31-08:00\",\n            \"event_id\": \"492264c1-deb5-49a4-850f-78411c30bce4\",\n            \"event_type\": \"ADD_LOGIN_ACTIVITY_DEVICE\",\n            \"ip_address\": \"Unknown IP\",\n            \"type\": \"event\",\n            \"session_id\": null,\n            \"additional_details\": null\n        },\n        {\n            \"source\": {\n                \"type\": \"user\",\n                \"id\": \"22222\",\n                \"name\": \"Example User 2\",\n                \"login\": \"user2@example.com\"\n            },\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"11111\",\n                \"name\": \"Example User\",\n                \"login\": \"user@example.com\"\n            },\n            \"created_at\": \"2015-12-02T09:41:31-08:00\",\n            \"event_id\": \"157c49ab-03b7-4ed1-a49c-82fb93ae558c\",\n            \"event_type\": \"LOGIN\",\n            \"ip_address\": \"Unknown IP\",\n            \"type\": \"event\",\n            \"session_id\": null,\n            \"additional_details\": null\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/file-requests/get_file_requests_id.json",
    "content": "{\n    \"id\": 42037322,\n    \"type\": \"file_request\",\n    \"created_at\": \"2020-09-28T10:53:43-08:00\",\n    \"created_by\": {\n        \"id\": 11446498,\n        \"type\": \"user\",\n        \"login\": \"ceo@example.com\",\n        \"name\": \"Aaron Levie\"\n    },\n    \"description\": \"Following documents are requested for your process\",\n    \"etag\": 1,\n    \"expires_at\": \"2020-09-28T10:53:43-08:00\",\n    \"folder\": {\n        \"id\": 12345,\n        \"type\": \"folder\",\n        \"etag\": 1,\n        \"name\": \"Contracts\",\n        \"sequence_id\": 3\n    },\n    \"is_description_required\": true,\n    \"is_email_required\": true,\n    \"status\": \"active\",\n    \"title\": \"Please upload documents\",\n    \"updated_at\": \"2020-09-28T10:53:43-08:00\",\n    \"updated_by\": {\n        \"id\": 11446498,\n        \"type\": \"user\",\n        \"login\": \"ceo@example.com\",\n        \"name\": \"Aaron Levie\"\n    },\n    \"url\": \"/f/19e57f40ace247278a8e3d336678c64a\"\n}\n"
  },
  {
    "path": "test/fixtures/file-requests/post_file_requests_id_copy.json",
    "content": "{\n    \"id\": 42037322,\n    \"type\": \"file_request\",\n    \"created_at\": \"2020-09-28T10:53:43-08:00\",\n    \"created_by\": {\n        \"id\": 11446498,\n        \"type\": \"user\",\n        \"login\": \"ceo@example.com\",\n        \"name\": \"Aaron Levie\"\n    },\n    \"description\": \"Following documents are requested for your process\",\n    \"etag\": 1,\n    \"expires_at\": \"2020-09-28T10:53:43-08:00\",\n    \"folder\": {\n        \"id\": 12345,\n        \"type\": \"folder\",\n        \"etag\": 1,\n        \"name\": \"Contracts\",\n        \"sequence_id\": 3\n    },\n    \"is_description_required\": true,\n    \"is_email_required\": true,\n    \"status\": \"active\",\n    \"title\": \"Please upload documents\",\n    \"updated_at\": \"2020-09-28T10:53:43-08:00\",\n    \"updated_by\": {\n        \"id\": 11446498,\n        \"type\": \"user\",\n        \"login\": \"ceo@example.com\",\n        \"name\": \"Aaron Levie\"\n    },\n    \"url\": \"/f/19e57f40ace247278a8e3d336678c64a\"\n}\n"
  },
  {
    "path": "test/fixtures/file-requests/put_file_requests_id.json",
    "content": "{\n    \"id\": 42037322,\n    \"type\": \"file_request\",\n    \"created_at\": \"2020-09-28T10:53:43-08:00\",\n    \"created_by\": {\n        \"id\": 11446498,\n        \"type\": \"user\",\n        \"login\": \"ceo@example.com\",\n        \"name\": \"Aaron Levie\"\n    },\n    \"description\": \"Following documents are requested for your process\",\n    \"etag\": 1,\n    \"expires_at\": \"2020-09-28T10:53:43-08:00\",\n    \"folder\": {\n        \"id\": 12345,\n        \"type\": \"folder\",\n        \"etag\": 1,\n        \"name\": \"Contracts\",\n        \"sequence_id\": 3\n    },\n    \"is_description_required\": true,\n    \"is_email_required\": true,\n    \"status\": \"active\",\n    \"title\": \"Please upload documents\",\n    \"updated_at\": \"2020-09-28T10:53:43-08:00\",\n    \"updated_by\": {\n        \"id\": 11446498,\n        \"type\": \"user\",\n        \"login\": \"ceo@example.com\",\n        \"name\": \"Aaron Levie\"\n    },\n    \"url\": \"/f/19e57f40ace247278a8e3d336678c64a\"\n}\n"
  },
  {
    "path": "test/fixtures/files/epic-poem.txt",
    "content": "The Project Gutenberg EBook of Beowulf\n\nThis eBook is for the use of anyone anywhere at no cost and with\nalmost no restrictions whatsoever.  You may copy it, give it away or\nre-use it under the terms of the Project Gutenberg License included\nwith this eBook or online at www.gutenberg.net\n\n\nTitle: Beowulf\n       An Anglo-Saxon Epic Poem, Translated From The Heyne-Socin\n       Text by Lesslie Hall\n\nAuthor:\n\nRelease Date: July 19, 2005 [EBook #16328]\n\nLanguage: English\n\nCharacter set encoding: ISO-8859-1\n\n*** START OF THIS PROJECT GUTENBERG EBOOK BEOWULF ***\n\n\n\n\nProduced by David Starner, Dainis Millers and the Online\nDistributed Proofreading Team at http://www.pgdp.net\n\n\n\n\n\n\n\nBEOWULF\nAN ANGLO-SAXON EPIC POEM\n\n_TRANSLATED FROM THE HEYNE-SOCIN TEXT_\n\nBY\n\nJNO: LESSLIE HALL, Ph. D. (J.H.U.)\n\nProfessor of English and History in The College of William and Mary\n\n\nD.C. HEATH & CO., PUBLISHERS\nBOSTON NEW YORK CHICAGO\n\n\nEntered according to Act of Congress, in the year 1892, by\n\nJNO: LESSLIE HALL,\n\nin the Office of the Librarian of Congress, at Washington.\n\n\nTO\n\nMy Wife\n\n[v]\n\n\n\n\nCONTENTS.\n\n\n                                                               PAGE\n\n      Preface                                                   vii\n\n      Bibliography of Translations                               xi\n\n      Glossary of Proper Names                                 xiii\n\n      List of Words and Phrases not in General Use            xviii\n\n      The Life and Death of Scyld (I.)                            1\n\n      Scyld's Successors\n                                 } (II.)                          3\n      Hrothgar's Great Mead-Hall\n\n      Grendel, the Murderer (III.)                                5\n\n      Beowulf Goes to Hrothgar's Assistance (IV.)                 8\n\n      The Geats Reach Heorot (V.)                                10\n\n      Beowulf Introduces Himself at the Palace (VI.)             12\n\n      Hrothgar and Beowulf (VII.)                                14\n\n      Hrothgar and Beowulf (continued) (VIII.)                   17\n\n      Unferth Taunts Beowulf (IX.)                               19\n\n      Beowulf Silences Unferth\n                               } (X.)                            21\n      Glee is High\n\n      All Sleep save One (XI.)                                   24\n\n      Grendel and Beowulf (XII.)                                 26\n\n      Grendel is Vanquished (XIII.)                              28\n\n      Rejoicing of the Danes (XIV.)                              30\n\n      Hrothgar's Gratitude (XV.)                                 33\n\n      Hrothgar Lavishes Gifts upon his Deliverer (XVI.)          35\n\n      Banquet (continued)\n                                       } (XVII.)                 37\n      The Scop's Song of Finn and Hn�f\n\n      The Finn Episode (continued)\n                                   } (XVIII.)                    39\n      The Banquet Continues\n\n      Beowulf Receives Further Honor (XIX.)                      41\n\n      The Mother of Grendel (XX.)                                44\n\n      Hrothgar's Account of the Monsters (XXI.)                  46\n\n      Beowulf Seeks Grendel's Mother (XXII.)                     48\n\n      Beowulf's Fight with Grendel's Mother (XXIII.)             51\n\n      Beowulf is Double-Conqueror (XXIV.)                        53\n\n[vi]  Beowulf Brings his Trophies\n                                  } (XXV.)                       57\n      Hrothgar's Gratitude\n\n      Hrothgar Moralizes\n                         } (XXVI.)                               60\n      Rest after Labor\n\n      Sorrow at Parting (XXVII.)                                 62\n\n      The Homeward Journey\n                           } (XXVIII.)                           64\n      The Two Queens\n\n      Beowulf and Higelac (XXIX.)                                67\n\n      Beowulf Narrates his Adventures to Higelac (XXX.)          69\n\n      Gift-Giving is Mutual (XXXI.)                              73\n\n      The Hoard and the Dragon (XXXII.)                          75\n\n      Brave Though Aged\n                        } (XXXIII.)                              78\n      Reminiscences\n\n      Beowulf Seeks the Dragon\n                               } (XXXIV.)                        81\n      Beowulf's Reminiscences\n\n      Reminiscences (continued)\n                                } (XXXV.)                        83\n      Beowulf's Last Battle\n\n      Wiglaf the Trusty\n                                                  } (XXXVI.)     88\n      Beowulf is Deserted by Friends and by Sword\n\n      The Fatal Struggle\n                             } (XXXVII.)                         91\n      Beowulf's Last Moments\n\n      Wiglaf Plunders the Dragon's Den\n                                       } (XXXVIII.)              93\n      Beowulf's Death\n\n      The Dead Foes\n                             } (XXXIX.)                          95\n      Wiglaf's Bitter Taunts\n\n      The Messenger of Death (XL.)                               97\n\n      The Messenger's Retrospect (XLI.)                          99\n\n      Wiglaf's Sad Story\n                            } (XLII.)                           103\n      The Hoard Carried Off\n\n      The Burning of Beowulf (XLIII.)                           106\n\n      Addenda                                                   109\n\n[vii]\n\n\n\n\nPREFACE.\n\n\nThe present work is a modest effort to reproduce approximately, in modern\nmeasures, the venerable epic, Beowulf. _Approximately_, I repeat; for a\nvery close reproduction of Anglo-Saxon verse would, to a large extent, be\nprose to a modern ear.\n\nThe Heyne-Socin text and glossary have been closely followed. Occasionally\na deviation has been made, but always for what seemed good and sufficient\nreason. The translator does not aim to be an editor. Once in a while,\nhowever, he has added a conjecture of his own to the emendations quoted\nfrom the criticisms of other students of the poem.\n\nThis work is addressed to two classes of readers. From both of these alike\nthe translator begs sympathy and co-operation. The Anglo-Saxon scholar he\nhopes to please by adhering faithfully to the original. The student of\nEnglish literature he aims to interest by giving him, in modern garb, the\nmost ancient epic of our race. This is a bold and venturesome undertaking;\nand yet there must be some students of the Teutonic past willing to follow\neven a daring guide, if they may read in modern phrases of the sorrows of\nHrothgar, of the prowess of Beowulf, and of the feelings that stirred the\nhearts of our forefathers in their primeval homes.\n\nIn order to please the larger class of readers, a regular cadence has been\nused, a measure which, while retaining the essential characteristics of\nthe original, permits the reader to see ahead of him in reading.\n\nPerhaps every Anglo-Saxon scholar has his own theory as to how Beowulf\nshould be translated. Some have given us prose versions of what we believe\nto be a great poem. Is it any reflection on our honored Kemble and Arnold\nto say that their translations fail to show a layman that Beowulf is\njustly called our first _epic_? Of those translators who have used verse,\nseveral have written from what would seem a mistaken point of view. Is it\nproper, for instance, that the grave and solemn speeches of Beowulf and\nHrothgar be put in ballad measures, tripping lightly and airily along? Or,\nagain, is it fitting that the rough martial music of Anglo-Saxon verse be\ninterpreted to us in the smooth measures of modern blank verse? Do we hear\nwhat has been beautifully called \"the clanging tread of a warrior in\nmail\"?\n\n[viii]\n\nOf all English translations of Beowulf, that of Professor Garnett alone\ngives any adequate idea of the chief characteristics of this great\nTeutonic epic.\n\nThe measure used in the present translation is believed to be as near a\nreproduction of the original as modern English affords. The cadences\nclosely resemble those used by Browning in some of his most striking\npoems. The four stresses of the Anglo-Saxon verse are retained, and as\nmuch thesis and anacrusis is allowed as is consistent with a regular\ncadence. Alliteration has been used to a large extent; but it was thought\nthat modern ears would hardly tolerate it on every line. End-rhyme has\nbeen used occasionally; internal rhyme, sporadically. Both have some\nwarrant in Anglo-Saxon poetry. (For end-rhyme, see 1_53, 1_54; for\ninternal rhyme, 2_21, 6_40.)\n\nWhat Gummere[1] calls the \"rime-giver\" has been studiously kept; _viz._,\nthe first accented syllable in the second half-verse always carries the\nalliteration; and the last accented syllable alliterates only\nsporadically. Alternate alliteration is occasionally used as in the\noriginal. (See 7_61, 8_5.)\n\nNo two accented syllables have been brought together, except occasionally\nafter a c�sural pause. (See 2_19 and 12_1.) Or, scientifically speaking,\nSievers's C type has been avoided as not consonant with the plan of\ntranslation. Several of his types, however, constantly occur; _e.g._ A and\na variant (/�x | /�x) (/�x�x | /�x); B and a variant (x�/ | x�/�) (x�x�/ |\nx�/�); a variant of D (/�x | /�x�x); E (/�x�x | /�). Anacrusis gives\nfurther variety to the types used in the translation.\n\nThe parallelisms of the original have been faithfully preserved. (_E.g._,\n1_16 and 1_17: \"Lord\" and \"Wielder of Glory\"; 1_30, 1_31, 1_32; 2_12 and\n2_13; 2_27 and 2_28; 3_5 and 3_6.) Occasionally, some loss has been\nsustained; but, on the other hand, a gain has here and there been made.\n\nThe effort has been made to give a decided flavor of archaism to the\ntranslation. All words not in keeping with the spirit of the poem have\nbeen avoided. Again, though many archaic words have been used, there are\nnone, it is believed, which are not found in standard modern poetry.\n\n[ix]\n\nWith these preliminary remarks, it will not be amiss to give an outline of\nthe story of the poem.\n\n\n_THE STORY._\n\n_Hrothgar, king of the Danes, or Scyldings, builds a great mead-hall, or\npalace, in which he hopes to feast his liegemen and to give them presents.\nThe joy of king and retainers is, however, of short duration. Grendel, the\nmonster, is seized with hateful jealousy. He cannot brook the sounds of\njoyance that reach him down in his fen-dwelling near the hall. Oft and\nanon he goes to the joyous building, bent on direful mischief. Thane after\nthane is ruthlessly carried off and devoured, while no one is found strong\nenough and bold enough to cope with the monster. For twelve years he\npersecutes Hrothgar and his vassals._\n\n_Over sea, a day's voyage off, Beowulf, of the Geats, nephew of Higelac,\nking of the Geats, hears of Grendel's doings and of Hrothgar's misery. He\nresolves to crush the fell monster and relieve the aged king. With\nfourteen chosen companions, he sets sail for Dane-land. Reaching that\ncountry, he soon persuades Hrothgar of his ability to help him. The hours\nthat elapse before night are spent in beer-drinking and conversation. When\nHrothgar's bedtime comes he leaves the hall in charge of Beowulf, telling\nhim that never before has he given to another the absolute wardship of his\npalace. All retire to rest, Beowulf, as it were, sleeping upon his arms._\n\n_Grendel comes, the great march-stepper, bearing God's anger. He seizes\nand kills one of the sleeping warriors. Then he advances towards Beowulf.\nA fierce and desperate hand-to-hand struggle ensues. No arms are used,\nboth combatants trusting to strength and hand-grip. Beowulf tears\nGrendel's shoulder from its socket, and the monster retreats to his den,\nhowling and yelling with agony and fury. The wound is fatal._\n\n_The next morning, at early dawn, warriors in numbers flock to the hall\nHeorot, to hear the news. Joy is boundless. Glee runs high. Hrothgar and\nhis retainers are lavish of gratitude and of gifts._\n\n_Grendel's mother, however, comes the next night to avenge his death. She\nis furious and raging. While Beowulf is sleeping in a room somewhat apart\n[x] from the quarters of the other warriors, she seizes one of Hrothgar's\nfavorite counsellors, and carries him off and devours him. Beowulf is\ncalled. Determined to leave Heorot entirely purified, he arms himself, and\ngoes down to look for the female monster. After traveling through the\nwaters many hours, he meets her near the sea-bottom. She drags him to her\nden. There he sees Grendel lying dead. After a desperate and almost fatal\nstruggle with the woman, he slays her, and swims upward in triumph, taking\nwith him Grendel's head._\n\n_Joy is renewed at Heorot. Congratulations crowd upon the victor. Hrothgar\nliterally pours treasures into the lap of Beowulf; and it is agreed among\nthe vassals of the king that Beowulf will be their next liegelord._\n\n_Beowulf leaves Dane-land. Hrothgar weeps and laments at his departure._\n\n_When the hero arrives in his own land, Higelac treats him as a\ndistinguished guest. He is the hero of the hour._\n\n_Beowulf subsequently becomes king of his own people, the Geats. After he\nhas been ruling for fifty years, his own neighborhood is wofully harried\nby a fire-spewing dragon. Beowulf determines to kill him. In the ensuing\nstruggle both Beowulf and the dragon are slain. The grief of the Geats is\ninexpressible. They determine, however, to leave nothing undone to honor\nthe memory of their lord. A great funeral-pyre is built, and his body is\nburnt. Then a memorial-barrow is made, visible from a great distance, that\nsailors afar may be constantly reminded of the prowess of the national\nhero of Geatland._\n\n_The poem closes with a glowing tribute to his bravery, his gentleness,\nhis goodness of heart, and his generosity._\n\n       *       *       *       *       *\n\nIt is the devout desire of this translator to hasten the day when the\nstory of Beowulf shall be as familiar to English-speaking peoples as that\nof the Iliad. Beowulf is our first great epic. It is an epitomized history\nof the life of the Teutonic races. It brings vividly before us our\nforefathers of pre-Alfredian eras, in their love of war, of sea, and of\nadventure.\n\nMy special thanks are due to Professors Francis A. March and James A.\nHarrison, for advice, sympathy, and assistance.\n\n                                                        J.L. HALL.\n\n[xi]\n\n\n\n\nABBREVIATIONS USED IN THE NOTES.\n\n\nB. = Bugge. C. = Cosijn. Gr. = Grein. Grdvtg. = Grundtvig. H. = Heyne. H.\nand S. = Harrison and Sharp. H.-So. = Heyne-Socin. K.= Kemble. Kl. =\nKluge. M.= M�llenhoff. R. = Rieger. S. = Sievers. Sw. = Sweet. t.B. = ten\nBrink. Th. = Thorpe. W. = W�lcker.\n\n       *       *       *       *       *\n\n\n\n\nBIBLIOGRAPHY OF TRANSLATIONS.\n\n\n~Arnold, Thomas.~--Beowulf. A heroic poem of the eighth century. London,\n1876. With English translation. Prose.\n\n~Botkine, L.~--Beowulf. Epop�e Anglo-Saxonne. Havre, 1877. First French\ntranslation. Passages occasionally omitted.\n\n~Conybeare, J.J.~--Illustrations of Anglo-Saxon Poetry. London, 1826. Full\nLatin translation, and some passages translated into English blank-verse.\n\n~Ettmuller, L.~--Beowulf, stabreimend �bersetzt. Z�rich, 1840.\n\n~Garnett, J.M.~--Beowulf: an Anglo-Saxon Poem, and the Fight at Finnsburg.\nBoston, 1882. An accurate line-for-line translation, using alliteration\noccasionally, and sometimes assuming a metrical cadence.\n\n~Grein, C.W.M.~--Dichtungen der Angelsachsen, stabreimend �bersetzt. 2\nBde. G�ttingen, 1857-59.\n\n~Grion, Giusto.~--Beovulf, poema epico anglo-sassone del VII. secolo,\ntradotto e illustrato. Lucca, 1883. First Italian translation.\n\n~Grundtvig, N.F.S.~--Bjowulfs Drape. Copenhagen, 1820.\n\n~Heyne, M.~--A translation in iambic measures. Paderborn, 1863.\n\n~Kemble, J.M.~--The Anglo-Saxon Poems of Beowulf, the Traveller's Song,\nand the Battle of Finnsburg. London, 1833. The second edition contains a\nprose translation of Beowulf.\n\n~Leo, H.~--Ueber Beowulf. Halle, 1839. Translations of extracts.\n\n[xii]\n\n~Lumsden, H.W.~--Beowulf, translated into modern rhymes. London, 1881.\nBallad measures. Passages occasionally omitted.\n\n~Sandras, G.S.~--De carminibus C�dmoni adjudicatis. Paris, 1859. An\nextract from Beowulf, with Latin translation.\n\n~Schaldmose, F.~--Beowulf og Scopes Widsith, to Angelsaxiske Digte.\nCopenhagen, 1847.\n\n~Simrock, K.~--Beowulf. Uebersetzt und erl�utert. Stuttgart und Augsburg,\n1859. Alliterative measures.\n\n~Thorkelin, G.J.~--De Danorum rebus gestis secul. III. et IV. poema\nDanicum dialecto Anglosaxonica. Havni�, 1815. Latin translation.\n\n~Thorpe, B.~--The Anglo-Saxon Poems of Beowulf, the Sc�p or Gleeman's\nTale, and the Fight at Finnsburg. Oxford, 1855. English translation in\nshort lines, generally containing two stresses.\n\n~Wackerbarth, A.D.~--Beowulf, translated into English verse. London, 1849.\n\n~Wickberg, R.~--Beowulf, en fornengelsk hjeltedikt, �fersatt. Westervik.\nFirst Swedish translation.\n\n~von Wolzogen, H.~--Beowulf, in alliterative measures. Leipzig.\n\n~Zinsser, G.~--Der Kampf Beowulfs mit Grendel. Jahresbericht of the\nRealschule at Forbach, 1881.\n\n[xiii]\n\n\n\n\nGLOSSARY OF PROPER NAMES.\n\n       *       *       *       *       *\n\n[The figures refer to the divisions of the poem in which the respective\nnames occur. The large figures refer to fitts, the small, to lines in the\nfitts.]\n\n       *       *       *       *       *\n\n~�lfhere~.--A kinsman of Wiglaf.--36_3.\n\n~�schere~.--Confidential friend of King Hrothgar. Elder brother of\nYrmenlaf. Killed by Grendel.--21_3; 30_89.\n\n~Beanstan~.--Father of Breca.--9_26.\n\n~Beowulf~.--Son of Scyld, the founder of the dynasty of Scyldings. Father\nof Healfdene, and grandfather of Hrothgar.--1_18; 2_1.\n\n~Beowulf~.--The hero of the poem. Sprung from the stock of Geats, son of\nEcgtheow. Brought up by his maternal grandfather Hrethel, and figuring in\nmanhood as a devoted liegeman of his uncle Higelac. A hero from his youth.\nHas the strength of thirty men. Engages in a swimming-match with Breca.\nGoes to the help of Hrothgar against the monster Grendel. Vanquishes\nGrendel and his mother. Afterwards becomes king of the Geats. Late in life\nattempts to kill a fire-spewing dragon, and is slain. Is buried with great\nhonors. His memorial mound.--6_26; 7_2; 7_9; 9_3; 9_8; 12_28; 12_43; 23_1,\netc.\n\n~Breca~.--Beowulf's opponent in the famous swimming-match.--9_8; 9_19;\n9_21; 9_22.\n\n~Brondings~.--A people ruled by Breca.--9_23.\n\n~Brosinga mene~.--A famous collar once owned by the Brosings.--19_7.\n\n~Cain~.--Progenitor of Grendel and other monsters.--2_56; 20_11.\n\n~D�ghrefn~.--A warrior of the Hugs, killed by Beowulf.--35_40.\n\n~Danes~.--Subjects of Scyld and his descendants, and hence often called\nScyldings. Other names for them are Victory-Scyldings, Honor-Scyldings,\nArmor-Danes, Bright-Danes, East-Danes, West-Danes, North-Danes,\nSouth-Danes, Ingwins, Hrethmen.--1_1; 2_1; 3_2; 5_14; 7_1, etc.\n\n~Ecglaf~.--Father of Unferth, who taunts Beowulf.--9_1.\n\n~Ecgtheow~.--Father of Beowulf, the hero of the poem. A widely-known\nW�gmunding warrior. Marries Hrethel's daughter. After slaying Heatholaf, a\nWylfing, he flees his country.--7_3; 5_6; 8_4.\n\n~Ecgwela~.--A king of the Danes before Scyld.--25_60.\n\n[xiv]\n\n~Elan~.--Sister of Hrothgar, and probably wife of Ongentheow, king of the\nSwedes.--2_10.\n\n~Eagle Cape~.--A promontory in Geat-land, under which took place Beowulf's\nlast encounter.--41_87.\n\n~Eadgils~.--Son of Ohthere and brother of Eanmund.--34_2.\n\n~Eanmund~.--Son of Ohthere and brother of Eadgils. The reference to these\nbrothers is vague, and variously understood. Heyne supposes as follows:\nRaising a revolt against their father, they are obliged to leave Sweden.\nThey go to the land of the Geats; with what intention, is not known, but\nprobably to conquer and plunder. The Geatish king, Heardred, is slain by\none of the brothers, probably Eanmund.--36_10; 31_54 to 31_60; 33_66 to\n34_6.\n\n~Eofor~.--A Geatish hero who slays Ongentheow in war, and is rewarded by\nHygelac with the hand of his only daughter.--41_18; 41_48.\n\n~Eormenric~.--A Gothic king, from whom Hama took away the famous Brosinga\nmene.--19_9.\n\n~Eom�r~.--Son of Offa and Thrytho, king and queen of the Angles.--28_69.\n\n~Finn~.--King of the North-Frisians and the Jutes. Marries Hildeburg. At\nhis court takes place the horrible slaughter in which the Danish general,\nHn�f, fell. Later on, Finn himself is slain by Danish warriors.--17_18;\n17_30; 17_44; 18_4; 18_23.\n\n~Fin-land~.--The country to which Beowulf was driven by the currents in\nhis swimming-match.--10_22.\n\n~Fitela~.--Son and nephew of King Sigemund, whose praises are sung in\nXIV.--14_42; 14_53.\n\n~Folcwalda~.--Father of Finn.--17_38.\n\n~Franks~.--Introduced occasionally in referring to the death of\nHigelac.--19_19; 40_21; 40_24.\n\n~Frisians~.--A part of them are ruled by Finn. Some of them were engaged\nin the struggle in which Higelac was slain.--17_20; 17_42; 17_52; 40_21.\n\n~Freaware~.--Daughter of King Hrothgar. Married to Ingeld, a Heathobard\nprince.--29_60; 30_32.\n\n~Froda~.--King of the Heathobards, and father of Ingeld.--29_62.\n\n~Garmund~.--Father of Offa.--28_71.\n\n~Geats, Geatmen~.--The race to which the hero of the poem belongs. Also\ncalled Weder-Geats, or Weders, War-Geats, Sea-Geats. They are ruled by\nHrethel, H�thcyn, Higelac, and Beowulf.--4_7; 7_4; 10_45; 11_8; 27_14;\n28_8.\n\n~Gepids~.--Named in connection with the Danes and Swedes.--35_34.\n\n~Grendel~.--A monster of the race of Cain. Dwells in the fens and moors.\nIs furiously envious when he hears sounds of joy in Hrothgar's palace.\nCauses the king untold agony for years. Is finally conquered by Beowulf,\nand dies of his wound. His hand and arm are hung up in Hrothgar's hall\nHeorot. His head is cut off by Beowulf when he goes down to fight with\nGrendel's mother.--2_50; 3_1; 3_13; 8_19; 11_17; 12_2; 13_27; 15_3.\n\n~Guthlaf~.--A Dane of Hn�f's party.--18_24.\n\n~Half-Danes~.--Branch of the Danes to which Hn�f belonged.--17_19.\n\n[xv]\n\n~Halga~.--Surnamed the Good. Younger brother of Hrothgar.--2_9.\n\n~Hama~.--Takes the Brosinga mene from Eormenric.--19_7.\n\n~H�reth~.--Father of Higelac's queen, Hygd.--28_39; 29_18.\n\n~H�thcyn~.--Son of Hrethel and brother of Higelac. Kills his brother\nHerebeald accidentally. Is slain at Ravenswood, fighting against\nOngentheow.--34_43; 35_23; 40_32.\n\n~Helmings~.--The race to which Queen Wealhtheow belonged.--10_63.\n\n~Heming~.--A kinsman of Garmund, perhaps nephew.--28_54; 28_70.\n\n~Hengest~.--A Danish leader. Takes command on the fall of Hn�f.--17_33;\n17_41.\n\n~Herebeald~.--Eldest son of Hrethel, the Geatish king, and brother of\nHigelac. Killed by his younger brother H�thcyn.--34_43; 34_47.\n\n~Heremod~.--A Danish king of a dynasty before the Scylding line. Was a\nsource of great sorrow to his people.--14_64; 25_59.\n\n~Hereric~.--Referred to as uncle of Heardred, but otherwise\nunknown.--31_60.\n\n~Hetwars~.--Another name for the Franks.--33_51.\n\n~Healfdene~.--Grandson of Scyld and father of Hrothgar. Ruled the Danes\nlong and well.--2_5; 4_1; 8_14.\n\n~Heardred~.--Son of Higelac and Hygd, king and queen of the Geats.\nSucceeds his father, with Beowulf as regent. Is slain by the sons of\nOhthere.--31_56; 33_63; 33_75.\n\n~Heathobards~.--Race of Lombards, of which Froda is king. After Froda\nfalls in battle with the Danes, Ingeld, his son, marries Hrothgar's\ndaughter, Freaware, in order to heal the feud.--30_1; 30_6.\n\n~Heatholaf~.--A Wylfing warrior slain by Beowulf's father.--8_5.\n\n~Heathoremes~.--The people on whose shores Breca is cast by the waves\nduring his contest with Beowulf.--9_21.\n\n~Heorogar~.--Elder brother of Hrothgar, and surnamed 'Weoroda R�swa,'\nPrince of the Troopers.--2_9; 8_12.\n\n~Hereward~.--Son of the above.--31_17.\n\n~Heort~, ~Heorot~.--The great mead-hall which King Hrothgar builds. It is\ninvaded by Grendel for twelve years. Finally cleansed by Beowulf, the\nGeat. It is called Heort on account of the hart-antlers which decorate\nit.--2_25; 3_32; 3_52.\n\n~Hildeburg~.--Wife of Finn, daughter of Hoce, and related to\nHn�f,--probably his sister.--17_21; 18_34.\n\n~Hn�f~.--Leader of a branch of the Danes called Half-Danes. Killed in the\nstruggle at Finn's castle.--17_19; 17_61.\n\n~Hondscio~.--One of Beowulf's companions. Killed by Grendel just before\nBeowulf grappled with that monster.--30_43.\n\n~Hoce~.--Father of Hildeburg and probably of Hn�f.--17_26.\n\n~Hrethel~.--King of the Geats, father of Higelac, and grandfather of\nBeowulf.--7_4; 34_39.\n\n~Hrethla~.--Once used for Hrethel.--7_82.\n\n~Hrethmen~.--Another name for the Danes.--7_73.\n\n~Hrethric~.--Son of Hrothgar.--18_65; 27_19.\n\n[xvi]\n\n~Hreosna-beorh~.--A promontory in Geat-land, near which Ohthere's sons\nmade plundering raids.--35_18.\n\n~Hrothgar~.--The Danish king who built the hall Heort, but was long unable\nto enjoy it on account of Grendel's persecutions. Marries Wealhtheow, a\nHelming lady. Has two sons and a daughter. Is a typical Teutonic king,\nlavish of gifts. A devoted liegelord, as his lamentations over slain\nliegemen prove. Also very appreciative of kindness, as is shown by his\nloving gratitude to Beowulf.--2_9; 2_12; 4_1; 8_10; 15_1; etc., etc.\n\n~Hrothmund~.--Son of Hrothgar.--18_65.\n\n~Hrothulf~.--Probably a son of Halga, younger brother of Hrothgar.\nCertainly on terms of close intimacy in Hrothgar's palace.--16_26; 18_57.\n\n~Hrunting~.--Unferth's sword, lent to Beowulf.--22_71; 25_9.\n\n~Hugs~.--A race in alliance with the Franks and Frisians at the time of\nHigelac's fall.--35_41.\n\n~Hun~.--A Frisian warrior, probably general of the Hetwars. Gives Hengest\na beautiful sword.--18_19.\n\n~Hunferth~.--Sometimes used for Unferth.\n\n~Hygelac~, ~Higelac~.--King of the Geats, uncle and liegelord of Beowulf,\nthe hero of the poem.--His second wife is the lovely Hygd, daughter of\nH�reth. The son of their union is Heardred. Is slain in a war with the\nHugs, Franks, and Frisians combined. Beowulf is regent, and afterwards\nking of the Geats.--4_6; 5_4; 28_34; 29_9; 29_21; 31_56.\n\n~Hygd~.--Wife of Higelac, and daughter of H�reth. There are some\nindications that she married Beowulf after she became a widow.--28_37.\n\n~Ingeld~.--Son of the Heathobard king, Froda. Marries Hrothgar's daughter,\nFreaware, in order to reconcile the two peoples.--29_62; 30_32.\n\n~Ingwins~.--Another name for the Danes.--16_52; 20_69.\n\n~Jutes~.--Name sometimes applied to Finn's people.--17_22; 17_38; 18_17.\n\n~Lafing~.--Name of a famous sword presented to Hengest by Hun.--18_19.\n\n~Merewing~.--A Frankish king, probably engaged in the war in which Higelac\nwas slain.--40_29.\n\n~N�gling~.--Beowulf's sword.--36_76.\n\n~Offa~.--King of the Angles, and son of Garmund. Marries the terrible\nThrytho who is so strongly contrasted with Hygd.--28_59; 28_66.\n\n~Ohthere~.--Son of Ongentheow, king of the Swedes. He is father of Eanmund\nand Eadgils.--40_35; 40_39.\n\n~Onela~.--Brother of Ohthere.--36_15; 40_39.\n\n~Ongentheow~.--King of Sweden, of the Scylfing dynasty. Married, perhaps,\nElan, daughter of Healfdene.--35_26; 41_16.\n\n~Oslaf~.--A Dane of Hn�f's party.--18_24.\n\n~Ravenswood~.--The forest near which H�thcyn was slain.--40_31; 40_41.\n\n~Scefing~.--Applied (1_4) to Scyld, and meaning 'son of Scef.'\n\n[xvii]\n\n~Scyld~.--Founder of the dynasty to which Hrothgar, his father, and\ngrandfather belonged. He dies, and his body is put on a vessel, and set\nadrift. He goes from Daneland just as he had come to it--in a bark.--1_4;\n1_19; 1_27.\n\n~Scyldings~.--The descendants of Scyld. They are also called\nHonor-Scyldings, Victory-Scyldings, War-Scyldings, etc. (See 'Danes,'\nabove.)--2_1; 7_1; 8_1.\n\n~Scylfings~.--A Swedish royal line to which Wiglaf belonged.--36_2.\n\n~Sigemund~.--Son of W�ls, and uncle and father of Fitela. His struggle\nwith a dragon is related in connection with Beowulf's deeds of\nprowess.--14_38; 14_47.\n\n~Swerting~.--Grandfather of Higelac, and father of Hrethel.--19_11.\n\n~Swedes~.--People of Sweden, ruled by the Scylfings.--35_13.\n\n~Thrytho~.--Wife of Offa, king of the Angles. Known for her fierce and\nunwomanly disposition. She is introduced as a contrast to the gentle Hygd,\nqueen of Higelac.--28_42; 28_56.\n\n~Unferth~.--Son of Ecglaf, and seemingly a confidential courtier of\nHrothgar. Taunts Beowulf for having taken part in the swimming-match.\nLends Beowulf his sword when he goes to look for Grendel's mother. In the\nMS. sometimes written _Hunferth_. 9_1; 18_41.\n\n~W�ls~.--Father of Sigemund.--14_60.\n\n~W�gmunding~.--A name occasionally applied to Wiglaf and Beowulf, and\nperhaps derived from a common ancestor, W�gmund.--36_6; 38_61.\n\n~Weders~.--Another name for Geats or Wedergeats.\n\n~Wayland~.--A fabulous smith mentioned in this poem and in other old\nTeutonic literature.--7_83.\n\n~Wendels~.--The people of Wulfgar, Hrothgar's messenger and retainer.\n(Perhaps = Vandals.)--6_30.\n\n~Wealhtheow~.--Wife of Hrothgar. Her queenly courtesy is well shown in the\npoem.--10_55.\n\n~Weohstan~, or ~Wihstan~.--A W�gmunding, and father of Wiglaf.--36_1.\n\n~Whale's Ness~.--A prominent promontory, on which Beowulf's mound was\nbuilt.--38_52; 42_76.\n\n~Wiglaf~.--Son of Wihstan, and related to Beowulf. He remains faithful to\nBeowulf in the fatal struggle with the fire-drake. Would rather die than\nleave his lord in his dire emergency.--36_1; 36_3; 36_28.\n\n~Wonred~.--Father of Wulf and Eofor.--41_20; 41_26.\n\n~Wulf~.--Son of Wonred. Engaged in the battle between Higelac's and\nOngentheow's forces, and had a hand-to-hand fight with Ongentheow himself.\nOngentheow disables him, and is thereupon slain by Eofor.--41_19; 41_29.\n\n~Wulfgar~.--Lord of the Wendels, and retainer of Hrothgar.--6_18; 6_30.\n\n~Wylfings~.--A people to whom belonged Heatholaf, who was slain by\nEcgtheow.--8_6; 8_16.\n\n~Yrmenlaf~.--Younger brother of �schere, the hero whose death grieved\nHrothgar so deeply.--21_4.\n\n[xviii]\n\n\n\n\nLIST OF WORDS AND PHRASES NOT IN GENERAL USE.\n\n\nATHELING.--Prince, nobleman.\n\nBAIRN.--Son, child.\n\nBARROW.--Mound, rounded hill, funeral-mound.\n\nBATTLE-SARK.--Armor.\n\nBEAKER.--Cup, drinking-vessel.\n\nBEGEAR.--Prepare.\n\nBIGHT.--Bay, sea.\n\nBILL.--Sword.\n\nBOSS.--Ornamental projection.\n\nBRACTEATE.--A round ornament on a necklace.\n\nBRAND.--Sword.\n\nBURN.--Stream.\n\nBURNIE.--Armor.\n\nCARLE.--Man, hero.\n\nEARL.--Nobleman, any brave man.\n\nEKE.--Also.\n\nEMPRISE.--Enterprise, undertaking.\n\nERST.--Formerly.\n\nERST-WORTHY.--Worthy for a long time past.\n\nFAIN.--Glad.\n\nFERRY.--Bear, carry.\n\nFEY.--Fated, doomed.\n\nFLOAT.--Vessel, ship.\n\nFOIN.--To lunge (Shaks.).\n\nGLORY OF KINGS.--God.\n\nGREWSOME.--Cruel, fierce.\n\nHEFT.--Handle, hilt; used by synecdoche for 'sword.'\n\nHELM.--Helmet, protector.\n\nHENCHMAN.--Retainer, vassal.\n\nHIGHT.--Am (was) named.\n\nHOLM.--Ocean, curved surface of the sea.\n\nHIMSEEMED.--(It) seemed to him.\n\nLIEF.--Dear, valued.\n\nMERE.--Sea; in compounds, 'mere-ways,' 'mere-currents,' etc.\n\nMICKLE.--Much.\n\nNATHLESS.--Nevertheless.\n\nNAZE.--Edge (nose).\n\nNESS.--Edge.\n\nNICKER.--Sea-beast.\n\nQUIT, QUITE.--Requite.\n\nRATHE.--Quickly.\n\nREAVE.--Bereave, deprive.\n\nSAIL-ROAD.--Sea.\n\nSETTLE.--Seat, bench.\n\nSKINKER.--One who pours.\n\nSOOTHLY.--Truly.\n\nSWINGE.--Stroke, blow.\n\nTARGE, TARGET.--Shield.\n\nTHROUGHLY.--Thoroughly.\n\nTOLD.--Counted.\n\nUNCANNY.--Ill-featured, grizzly.\n\nUNNETHE.--Difficult.\n\nWAR-SPEED.--Success in war.\n\nWEB.--Tapestry (that which is 'woven').\n\nWEEDED.--Clad (cf. widow's weeds).\n\nWEEN.--Suppose, imagine.\n\nWEIRD.--Fate, Providence.\n\nWHILOM.--At times, formerly, often.\n\nWIELDER.--Ruler. Often used of God; also in compounds, as 'Wielder of\nGlory,' 'Wielder of Worship.'\n\nWIGHT.--Creature.\n\nWOLD.--Plane, extended surface.\n\nWOT.--Knows.\n\nYOUNKER.--Youth.\n\n[1]\n\n\n\n\nBEOWULF.\n\n\n\n\nI.\n\nTHE LIFE AND DEATH OF SCYLD.\n\n\n{The famous race of Spear-Danes.}\n\n          Lo! the Spear-Danes' glory through splendid achievements\n          The folk-kings' former fame we have heard of,\n          How princes displayed then their prowess-in-battle.\n\n{Scyld, their mighty king, in honor of whom they are often called\nScyldings. He is the great-grandfather of Hrothgar, so prominent in the\npoem.}\n\n          Oft Scyld the Scefing from scathers in numbers\n        5 From many a people their mead-benches tore.\n          Since first he found him friendless and wretched,\n          The earl had had terror: comfort he got for it,\n          Waxed 'neath the welkin, world-honor gained,\n          Till all his neighbors o'er sea were compelled to\n       10 Bow to his bidding and bring him their tribute:\n          An excellent atheling! After was borne him\n\n{A son is born to him, who receives the name of Beowulf--a name afterwards\nmade so famous by the hero of the poem.}\n\n          A son and heir, young in his dwelling,\n          Whom God-Father sent to solace the people.\n          He had marked the misery malice had caused them,\n       15 [1]That reaved of their rulers they wretched had erstwhile[2]\n          Long been afflicted. The Lord, in requital,\n          Wielder of Glory, with world-honor blessed him.\n          Famed was Beowulf, far spread the glory\n          Of Scyld's great son in the lands of the Danemen.\n\n[2]\n\n{The ideal Teutonic king lavishes gifts on his vassals.}\n\n       20 So the carle that is young, by kindnesses rendered\n          The friends of his father, with fees in abundance\n          Must be able to earn that when age approacheth\n          Eager companions aid him requitingly,\n          When war assaults him serve him as liegemen:\n       25 By praise-worthy actions must honor be got\n          'Mong all of the races. At the hour that was fated\n\n{Scyld dies at the hour appointed by Fate.}\n\n          Scyld then departed to the All-Father's keeping\n          Warlike to wend him; away then they bare him\n          To the flood of the current, his fond-loving comrades,\n       30 As himself he had bidden, while the friend of the Scyldings\n          Word-sway wielded, and the well-lov�d land-prince\n          Long did rule them.[3] The ring-stemm�d vessel,\n          Bark of the atheling, lay there at anchor,\n          Icy in glimmer and eager for sailing;\n\n{By his own request, his body is laid on a vessel and wafted seaward.}\n\n       35 The belov�d leader laid they down there,\n          Giver of rings, on the breast of the vessel,\n          The famed by the mainmast. A many of jewels,\n          Of fretted embossings, from far-lands brought over,\n          Was placed near at hand then; and heard I not ever\n       40 That a folk ever furnished a float more superbly\n          With weapons of warfare, weeds for the battle,\n          Bills and burnies; on his bosom sparkled\n          Many a jewel that with him must travel\n          On the flush of the flood afar on the current.\n       45 And favors no fewer they furnished him soothly,\n          Excellent folk-gems, than others had given him\n\n{He leaves Daneland on the breast of a bark.}\n\n          Who when first he was born outward did send him\n          Lone on the main, the merest of infants:\n          And a gold-fashioned standard they stretched under heaven\n[3]    50 High o'er his head, let the holm-currents bear him,\n          Seaward consigned him: sad was their spirit,\n          Their mood very mournful. Men are not able\n\n{No one knows whither the boat drifted.}\n\n          Soothly to tell us, they in halls who reside,[4]\n          Heroes under heaven, to what haven he hied.\n\n    [1] For the '��t' of verse 15, Sievers suggests '��' (= which). If\n    this be accepted, the sentence 'He had ... afflicted' will read: _He_\n    (_i.e._ God) _had perceived the malice-caused sorrow which they,\n    lordless, had formerly long endured_.\n\n    [2] For 'aldor-l�ase' (15) Gr. suggested 'aldor-ceare': _He perceived\n    their distress, that they formerly had suffered life-sorrow a long\n    while_.\n\n    [3] A very difficult passage. '�hte' (31) has no object. H. supplies\n    'geweald' from the context; and our translation is based upon this\n    assumption, though it is far from satisfactory. Kl. suggests\n    'l�ndagas' for 'lange': _And the beloved land-prince enjoyed (had) his\n    transitory days (i.e. lived)_. B. suggests a dislocation; but this is\n    a dangerous doctrine, pushed rather far by that eminent scholar.\n\n    [4] The reading of the H.-So. text has been quite closely followed;\n    but some eminent scholars read 's�le-r�denne' for 'sele-r�dende.' If\n    that be adopted, the passage will read: _Men cannot tell us, indeed,\n    the order of Fate, etc._ 'Sele-r�dende' has two things to support it:\n    (1) v. 1347; (2) it affords a parallel to 'men' in v. 50.\n\n\n\n\nII.\n\nSCYLD'S SUCCESSORS.--HROTHGAR'S GREAT MEAD-HALL.\n\n\n{Beowulf succeeds his father Scyld}\n\n          In the boroughs then Beowulf, bairn of the Scyldings,\n          Belov�d land-prince, for long-lasting season\n          Was famed mid the folk (his father departed,\n          The prince from his dwelling), till afterward sprang\n        5 Great-minded Healfdene; the Danes in his lifetime\n          He graciously governed, grim-mooded, ag�d.\n\n{Healfdene's birth.}\n\n          Four bairns of his body born in succession\n          Woke in the world, war-troopers' leader\n          Heorogar, Hrothgar, and Halga the good;\n       10 Heard I that Elan was Ongentheow's consort,\n\n{He has three sons--one of them, Hrothgar--and a daughter named Elan.\nHrothgar becomes a mighty king.}\n\n          The well-beloved bedmate of the War-Scylfing leader.\n          Then glory in battle to Hrothgar was given,\n          Waxing of war-fame, that willingly kinsmen\n          Obeyed his bidding, till the boys grew to manhood,\n       15 A numerous band.  It burned in his spirit\n          To urge his folk to found a great building,\n          A mead-hall grander than men of the era\n\n{He is eager to build a great hall in which he may feast his retainers}\n\n          Ever had heard of, and in it to share\n          With young and old all of the blessings\n       20 The Lord had allowed him, save life and retainers.\n          Then the work I find afar was assigned\n[4]       To many races in middle-earth's regions,\n          To adorn the great folk-hall. In due time it happened\n          Early 'mong men, that 'twas finished entirely,\n       25 The greatest of hall-buildings; Heorot he named it\n\n{The hall is completed, and is called Heort, or Heorot.}\n\n          Who wide-reaching word-sway wielded 'mong earlmen.\n          His promise he brake not, rings he lavished,\n          Treasure at banquet. Towered the hall up\n          High and horn-crested, huge between antlers:\n       30 It battle-waves bided, the blasting fire-demon;\n          Ere long then from hottest hatred must sword-wrath\n          Arise for a woman's husband and father.\n          Then the mighty war-spirit[1] endured for a season,\n\n{The Monster Grendel is madly envious of the Danemen's joy.}\n\n          Bore it bitterly, he who bided in darkness,\n       35 That light-hearted laughter loud in the building\n          Greeted him daily; there was dulcet harp-music,\n          Clear song of the singer. He said that was able\n\n{[The course of the story is interrupted by a short reference to some old\naccount of the creation.]}\n\n          To tell from of old earthmen's beginnings,\n          That Father Almighty earth had created,\n       40 The winsome wold that the water encircleth,\n          Set exultingly the sun's and the moon's beams\n          To lavish their lustre on land-folk and races,\n          And earth He embellished in all her regions\n          With limbs and leaves; life He bestowed too\n       45 On all the kindreds that live under heaven.\n\n{The glee of the warriors is overcast by a horrible dread.}\n\n          So blessed with abundance, brimming with joyance,\n          The warriors abided, till a certain one gan to\n          Dog them with deeds of direfullest malice,\n          A foe in the hall-building: this horrible stranger[2]\n       50 Was Grendel entitled, the march-stepper famous\n          Who[3] dwelt in the moor-fens, the marsh and the fastness;\n          The wan-mooded being abode for a season\n[5]       In the land of the giants, when the Lord and Creator\n          Had banned him and branded. For that bitter murder,\n       55 The killing of Abel, all-ruling Father\n\n{Cain is referred to as a progenitor of Grendel, and of monsters in\ngeneral.}\n\n          The kindred of Cain crushed with His vengeance;\n          In the feud He rejoiced not, but far away drove him\n          From kindred and kind, that crime to atone for,\n          Meter of Justice. Thence ill-favored creatures,\n       60 Elves and giants, monsters of ocean,\n          Came into being, and the giants that longtime\n          Grappled with God; He gave them requital.\n\n    [1] R. and t. B. prefer 'ellor-g�st' to 'ellen-g�st' (86): _Then the\n    stranger from afar endured, etc._\n\n    [2] Some authorities would translate '_demon_' instead of\n    '_stranger_.'\n\n    [3] Some authorities arrange differently, and render: _Who dwelt in\n    the moor-fens, the marsh and the fastness, the land of the\n    giant-race._\n\n\n\n\nIII.\n\nGRENDEL THE MURDERER.\n\n\n{Grendel attacks the sleeping heroes}\n\n          When the sun was sunken, he set out to visit\n          The lofty hall-building, how the Ring-Danes had used it\n          For beds and benches when the banquet was over.\n          Then he found there reposing many a noble\n        5 Asleep after supper; sorrow the heroes,[1]\n          Misery knew not. The monster of evil\n          Greedy and cruel tarried but little,\n\n{He drags off thirty of them, and devours them}\n\n          Fell and frantic, and forced from their slumbers\n          Thirty of thanemen; thence he departed\n       10 Leaping and laughing, his lair to return to,\n          With surfeit of slaughter sallying homeward.\n          In the dusk of the dawning, as the day was just breaking,\n          Was Grendel's prowess revealed to the warriors:\n\n{A cry of agony goes up, when Grendel's horrible deed is fully realized.}\n\n          Then, his meal-taking finished, a moan was uplifted,\n       15 Morning-cry mighty. The man-ruler famous,\n          The long-worthy atheling, sat very woful,\n          Suffered great sorrow, sighed for his liegemen,\n[6]       When they had seen the track of the hateful pursuer,\n          The spirit accurs�d: too crushing that sorrow,\n\n{The monster returns the next night.}\n\n       20 Too loathsome and lasting. Not longer he tarried,\n          But one night after continued his slaughter\n          Shameless and shocking, shrinking but little\n          From malice and murder; they mastered him fully.\n          He was easy to find then who otherwhere looked for\n       25 A pleasanter place of repose in the lodges,\n          A bed in the bowers. Then was brought to his notice\n          Told him truly by token apparent\n          The hall-thane's hatred: he held himself after\n          Further and faster who the foeman did baffle.\n       30 [2]So ruled he and strongly strove against justice\n          Lone against all men, till empty uptowered\n\n{King Hrothgar's agony and suspense last twelve years.}\n\n          The choicest of houses. Long was the season:\n          Twelve-winters' time torture suffered\n          The friend of the Scyldings, every affliction,\n       35 Endless agony; hence it after[3] became\n          Certainly known to the children of men\n          Sadly in measures, that long against Hrothgar\n          Grendel struggled:--his grudges he cherished,\n          Murderous malice, many a winter,\n       40 Strife unremitting, and peacefully wished he\n          [4]Life-woe to lift from no liegeman at all of\n          The men of the Dane-folk, for money to settle,\n          No counsellor needed count for a moment\n[7]       On handsome amends at the hands of the murderer;\n\n{Grendel is unremitting in his persecutions.}\n\n       45 The monster of evil fiercely did harass,\n          The ill-planning death-shade, both elder and younger,\n          Trapping and tricking them. He trod every night then\n          The mist-covered moor-fens; men do not know where\n          Witches and wizards wander and ramble.\n       50 So the foe of mankind many of evils\n          Grievous injuries, often accomplished,\n          Horrible hermit; Heort he frequented,\n          Gem-bedecked palace, when night-shades had fallen\n\n{God is against the monster.}\n\n          (Since God did oppose him, not the throne could he touch,[5]\n       55 The light-flashing jewel, love of Him knew not).\n          'Twas a fearful affliction to the friend of the Scyldings\n\n{The king and his council deliberate in vain.}\n\n          Soul-crushing sorrow. Not seldom in private\n          Sat the king in his council; conference held they\n          What the braves should determine 'gainst terrors unlooked for.\n\n{They invoke the aid of their gods.}\n\n       60 At the shrines of their idols often they promised\n          Gifts and offerings, earnestly prayed they\n          The devil from hell would help them to lighten\n          Their people's oppression. Such practice they used then,\n          Hope of the heathen; hell they remembered\n       65 In innermost spirit, God they knew not,\n\n{The true God they do not know.}\n\n          Judge of their actions, All-wielding Ruler,\n          No praise could they give the Guardian of Heaven,\n          The Wielder of Glory. Woe will be his who\n          Through furious hatred his spirit shall drive to\n       70 The clutch of the fire, no comfort shall look for,\n          Wax no wiser; well for the man who,\n          Living his life-days, his Lord may face\n          And find defence in his Father's embrace!\n\n    [1] The translation is based on 'weras,' adopted by H.-So.--K. and Th.\n    read 'wera' and, arranging differently, render 119(2)-120: _They knew\n    not sorrow, the wretchedness of man, aught of misfortune_.--For\n    'unh�lo' (120) R. suggests 'unf�lo': _The uncanny creature, greedy and\n    cruel, etc_.\n\n    [2] S. rearranges and translates: _So he ruled and struggled unjustly,\n    one against all, till the noblest of buildings stood useless (it was a\n    long while) twelve years' time: the friend of the Scyldings suffered\n    distress, every woe, great sorrows, etc_.\n\n    [3] For 'sy��an,' B. suggests 's�rcwidum': _Hence in mournful words it\n    became well known, etc_. Various other words beginning with 's' have\n    been conjectured.\n\n    [4] The H.-So. glossary is very inconsistent in referring to this\n    passage.--'Sibbe' (154), which H.-So. regards as an instr., B. takes\n    as accus., obj. of 'wolde.' Putting a comma after Deniga, he renders:\n    _He did not desire peace with any of the Danes, nor did he wish to\n    remove their life-woe, nor to settle for money_.\n\n    [5] Of this difficult passage the following interpretations among\n    others are given: (1) Though Grendel has frequented Heorot as a demon,\n    he could not become ruler of the Danes, on account of his hostility to\n    God. (2) Hrothgar was much grieved that Grendel had not appeared\n    before his throne to receive presents. (3) He was not permitted to\n    devastate the hall, on account of the Creator; _i.e._ God wished to\n    make his visit fatal to him.--Ne ... wisse (169) W. renders: _Nor had\n    he any desire to do so_; 'his' being obj. gen. = danach.\n\n[8]\n\n\n\n\nIV.\n\nBEOWULF GOES TO HROTHGAR'S ASSISTANCE.\n\n\n{Hrothgar sees no way of escape from the persecutions of Grendel.}\n\n          So Healfdene's kinsman constantly mused on\n          His long-lasting sorrow; the battle-thane clever\n          Was not anywise able evils to 'scape from:\n          Too crushing the sorrow that came to the people,\n        5 Loathsome and lasting the life-grinding torture,\n\n{Beowulf, the Geat, hero of the poem, hears of Hrothgar's sorrow, and\nresolves to go to his assistance.}\n\n          Greatest of night-woes. So Higelac's liegeman,\n          Good amid Geatmen, of Grendel's achievements\n          Heard in his home:[1] of heroes then living\n          He was stoutest and strongest, sturdy and noble.\n       10 He bade them prepare him a bark that was trusty;\n          He said he the war-king would seek o'er the ocean,\n          The folk-leader noble, since he needed retainers.\n          For the perilous project prudent companions\n          Chided him little, though loving him dearly;\n       15 They egged the brave atheling, augured him glory.\n\n{With fourteen carefully chosen companions, he sets out for Dane-land.}\n\n          The excellent knight from the folk of the Geatmen\n          Had liegemen selected, likest to prove them\n          Trustworthy warriors; with fourteen companions\n          The vessel he looked for; a liegeman then showed them,\n       20 A sea-crafty man, the bounds of the country.\n          Fast the days fleeted; the float was a-water,\n          The craft by the cliff. Clomb to the prow then\n          Well-equipped warriors: the wave-currents twisted\n          The sea on the sand; soldiers then carried\n       25 On the breast of the vessel bright-shining jewels,\n          Handsome war-armor; heroes outshoved then,\n          Warmen the wood-ship, on its wished-for adventure.\n\n[9]\n\n{The vessel sails like a bird}\n\n          The foamy-necked floater fanned by the breeze,\n          Likest a bird, glided the waters,\n\n{In twenty four hours they reach the shores of Hrothgar's dominions}\n\n       30 Till twenty and four hours thereafter\n          The twist-stemmed vessel had traveled such distance\n          That the sailing-men saw the sloping embankments,\n          The sea cliffs gleaming, precipitous mountains,\n          Nesses enormous: they were nearing the limits\n       35 At the end of the ocean.[2] Up thence quickly\n          The men of the Weders clomb to the mainland,\n          Fastened their vessel (battle weeds rattled,\n          War burnies clattered), the Wielder they thanked\n          That the ways o'er the waters had waxen so gentle.\n\n{They are hailed by the Danish coast guard}\n\n       40 Then well from the cliff edge the guard of the Scyldings\n          Who the sea-cliffs should see to, saw o'er the gangway\n          Brave ones bearing beauteous targets,\n          Armor all ready, anxiously thought he,\n          Musing and wondering what men were approaching.\n       45 High on his horse then Hrothgar's retainer\n          Turned him to coastward, mightily brandished\n          His lance in his hands, questioned with boldness.\n\n{His challenge}\n\n          \"Who are ye men here, mail-covered warriors\n          Clad in your corslets, come thus a-driving\n       50 A high riding ship o'er the shoals of the waters,\n          [3]And hither 'neath helmets have hied o'er the ocean?\n[10]      I have been strand-guard, standing as warden,\n          Lest enemies ever anywise ravage\n          Danish dominions with army of war-ships.\n       55 More boldly never have warriors ventured\n          Hither to come; of kinsmen's approval,\n          Word-leave of warriors, I ween that ye surely\n\n{He is struck by Beowulf's appearance.}\n\n          Nothing have known. Never a greater one\n          Of earls o'er the earth have _I_ had a sight of\n       60 Than is one of your number, a hero in armor;\n          No low-ranking fellow[4] adorned with his weapons,\n          But launching them little, unless looks are deceiving,\n          And striking appearance. Ere ye pass on your journey\n          As treacherous spies to the land of the Scyldings\n       65 And farther fare, I fully must know now\n          What race ye belong to. Ye far-away dwellers,\n          Sea-faring sailors, my simple opinion\n          Hear ye and hearken: haste is most fitting\n          Plainly to tell me what place ye are come from.\"\n\n    [1] 'From h�m' (194) is much disputed. One rendering is: _Beowulf,\n    being away from home, heard of Hrothgar's troubles, etc_. Another,\n    that adopted by S. and endorsed in the H.-So. notes, is: _B. heard\n    from his neighborhood (neighbors),_ i.e. _in his home, etc_. A third\n    is: _B., being at home, heard this as occurring away from home_. The\n    H.-So. glossary and notes conflict.\n\n    [2] 'Eoletes' (224) is marked with a (?) by H.-So.; our rendering\n    simply follows his conjecture.--Other conjectures as to 'eolet' are:\n    (1) _voyage_, (2) _toil_, _labor_, (3) _hasty journey_.\n\n    [3] The lacuna of the MS at this point has been supplied by various\n    conjectures. The reading adopted by H.-So. has been rendered in the\n    above translation. W., like H.-So., makes 'ic' the beginning of a new\n    sentence, but, for 'helmas b�ron,' he reads 'hringed stefnan.' This\n    has the advantage of giving a parallel to 'brontne ceol' instead of a\n    kenning for 'go.'--B puts the (?) after 'holmas', and begins a new\n    sentence at the middle of the line. Translate: _What warriors are ye,\n    clad in armor, who have thus come bringing the foaming vessel over the\n    water way, hither over the seas? For some time on the wall I have been\n    coast guard, etc_. S. endorses most of what B. says, but leaves out\n    'on the wall' in the last sentence. If W.'s 'hringed stefnan' be\n    accepted, change line 51 above to, _A ring-stemmed vessel hither\n    o'ersea_.\n\n    [4] 'Seld-guma' (249) is variously rendered: (1) _housecarle_; (2)\n    _home-stayer_; (3) _common man_. Dr. H. Wood suggests _a man-at-arms\n    in another's house_.\n\n\n\n\nV.\n\nTHE GEATS REACH HEOROT.\n\n\n{Beowulf courteously replies.}\n\n          The chief of the strangers rendered him answer,\n          War-troopers' leader, and word-treasure opened:\n\n{We are Geats.}\n\n          \"We are sprung from the lineage of the people of Geatland,\n          And Higelac's hearth-friends. To heroes unnumbered\n\n{My father Ecgtheow was well-known in his day.}\n\n        5 My father was known, a noble head-warrior\n          Ecgtheow titled; many a winter\n          He lived with the people, ere he passed on his journey,\n          Old from his dwelling; each of the counsellors\n          Widely mid world-folk well remembers him.\n\n{Our intentions towards King Hrothgar are of the kindest.}\n\n       10 We, kindly of spirit, the lord of thy people,\n          The son of King Healfdene, have come here to visit,\n[11]      Folk-troop's defender: be free in thy counsels!\n          To the noble one bear we a weighty commission,\n          The helm of the Danemen; we shall hide, I ween,\n\n{Is it true that a monster is slaying Danish heroes?}\n\n       15 Naught of our message. Thou know'st if it happen,\n          As we soothly heard say, that some savage despoiler,\n          Some hidden pursuer, on nights that are murky\n          By deeds very direful 'mid the Danemen exhibits\n          Hatred unheard of, horrid destruction\n       20 And the falling of dead. From feelings least selfish\n\n{I can help your king to free himself from this horrible creature.}\n\n          I am able to render counsel to Hrothgar,\n          How he, wise and worthy, may worst the destroyer,\n          If the anguish of sorrow should ever be lessened,[1]\n          Comfort come to him, and care-waves grow cooler,\n       25 Or ever hereafter he agony suffer\n          And troublous distress, while towereth upward\n          The handsomest of houses high on the summit.\"\n\n{The coast-guard reminds Beowulf that it is easier to say than to do.}\n\n          Bestriding his stallion, the strand-watchman answered,\n          The doughty retainer: \"The difference surely\n       30 'Twixt words and works, the warlike shield-bearer\n          Who judgeth wisely well shall determine.\n          This band, I hear, beareth no malice\n\n{I am satisfied of your good intentions, and shall lead you to the\npalace.}\n\n          To the prince of the Scyldings. Pass ye then onward\n          With weapons and armor. I shall lead you in person;\n       35 To my war-trusty vassals command I shall issue\n          To keep from all injury your excellent vessel,\n\n{Your boat shall be well cared for during your stay here.}\n\n          Your fresh-tarred craft, 'gainst every opposer\n          Close by the sea-shore, till the curved-neck�d bark shall\n          Waft back again the well-beloved hero\n       40 O'er the way of the water to Weder dominions.\n\n{He again compliments Beowulf.}\n\n          To warrior so great 'twill be granted sure\n          In the storm of strife to stand secure.\"\n          Onward they fared then (the vessel lay quiet,\n          The broad-bosomed bark was bound by its cable,\n[12]   45 Firmly at anchor); the boar-signs glistened[2]\n          Bright on the visors vivid with gilding,\n          Blaze-hardened, brilliant; the boar acted warden.\n          The heroes hastened, hurried the liegemen,\n\n{The land is perhaps rolling.}\n\n          Descended together, till they saw the great palace,\n       50 The well-fashioned wassail-hall wondrous and gleaming:\n\n{Heorot flashes on their view.}\n\n          'Mid world-folk and kindreds that was widest reputed\n          Of halls under heaven which the hero abode in;\n          Its lustre enlightened lands without number.\n          Then the battle-brave hero showed them the glittering\n       55 Court of the bold ones, that they easily thither\n          Might fare on their journey; the aforementioned warrior\n          Turning his courser, quoth as he left them:\n\n{The coast-guard, having discharged his duty, bids them God-speed.}\n\n          \"'Tis time I were faring; Father Almighty\n          Grant you His grace, and give you to journey\n       60 Safe on your mission! To the sea I will get me\n          'Gainst hostile warriors as warden to stand.\"\n\n    [1] 'Edwendan' (280) B. takes to be the subs. 'edwenden' (cf. 1775);\n    and 'bisigu' he takes as gen. sing., limiting 'edwenden': _If\n    reparation for sorrows is ever to come_. This is supported by t.B.\n\n    [2] Combining the emendations of B. and t.B., we may read: _The\n    boar-images glistened ... brilliant, protected the life of the\n    war-mooded man_. They read 'ferh-wearde' (305) and 'g��m�dgum men'\n    (306).\n\n\n\n\nVI.\n\nBEOWULF INTRODUCES HIMSELF AT THE PALACE.\n\n\n          The highway glistened with many-hued pebble,\n          A by-path led the liegemen together.\n          [1]Firm and hand-locked the war-burnie glistened,\n          The ring-sword radiant rang 'mid the armor\n        5 As the party was approaching the palace together\n\n{They set their arms and armor against the wall.}\n\n          In warlike equipments. 'Gainst the wall of the building\n          Their wide-fashioned war-shields they weary did set then,\n[13]      Battle-shields sturdy; benchward they turned then;\n          Their battle-sarks rattled, the gear of the heroes;\n       10 The lances stood up then, all in a cluster,\n          The arms of the seamen, ashen-shafts mounted\n          With edges of iron: the armor-clad troopers\n\n{A Danish hero asks them whence and why they are come.}\n\n          Were decked with weapons. Then a proud-mooded hero\n          Asked of the champions questions of lineage:\n       15 \"From what borders bear ye your battle-shields plated,\n          Gilded and gleaming, your gray-colored burnies,\n          Helmets with visors and heap of war-lances?--\n          To Hrothgar the king I am servant and liegeman.\n          'Mong folk from far-lands found I have never\n\n{He expresses no little admiration for the strangers.}\n\n       20 Men so many of mien more courageous.\n          I ween that from valor, nowise as outlaws,\n          But from greatness of soul ye sought for King Hrothgar.\"\n\n{Beowulf replies.}\n\n          Then the strength-famous earlman answer rendered,\n          The proud-mooded Wederchief replied to his question,\n\n{We are Higelac's table-companions, and bear an important commission to\nyour prince.}\n\n       25 Hardy 'neath helmet: \"Higelac's mates are we;\n          Beowulf hight I. To the bairn of Healfdene,\n          The famous folk-leader, I freely will tell\n          To thy prince my commission, if pleasantly hearing\n          He'll grant we may greet him so gracious to all men.\"\n       30 Wulfgar replied then (he was prince of the Wendels,\n          His boldness of spirit was known unto many,\n          His prowess and prudence): \"The prince of the Scyldings,\n\n{Wulfgar, the thane, says that he will go and ask Hrothgar whether he will\nsee the strangers.}\n\n          The friend-lord of Danemen, I will ask of thy journey,\n          The giver of rings, as thou urgest me do it,\n       35 The folk-chief famous, and inform thee early\n          What answer the good one mindeth to render me.\"\n          He turned then hurriedly where Hrothgar was sitting,\n          [2]Old and hoary, his earlmen attending him;\n          The strength-famous went till he stood at the shoulder\n       40 Of the lord of the Danemen, of courteous thanemen\n          The custom he minded. Wulfgar addressed then\n          His friendly liegelord: \"Folk of the Geatmen\n\n[14]\n\n{He thereupon urges his liegelord to receive the visitors courteously.}\n\n          O'er the way of the waters are wafted hither,\n          Faring from far-lands: the foremost in rank\n       45 The battle-champions Beowulf title.\n          They make this petition: with thee, O my chieftain,\n          To be granted a conference; O gracious King Hrothgar,\n          Friendly answer refuse not to give them!\n\n{Hrothgar, too, is struck with Beowulf's appearance.}\n\n          In war-trappings weeded worthy they seem\n       50 Of earls to be honored; sure the atheling is doughty\n          Who headed the heroes hitherward coming.\"\n\n    [1] Instead of the punctuation given by H.-So, S. proposed to insert a\n    comma after 'sc�r' (322), and to take 'hring-�ren' as meaning\n    'ring-mail' and as parallel with 'g��-byrne.' The passage would then\n    read: _The firm and hand-locked war-burnie shone, bright ring-mail,\n    rang 'mid the armor, etc_.\n\n    [2] Gr. and others translate 'unh�r' by 'bald'; _old and bald_.\n\n\n\n\nVII.\n\nHROTHGAR AND BEOWULF.\n\n\n{Hrothgar remembers Beowulf as a youth, and also remembers his father.}\n\n          Hrothgar answered, helm of the Scyldings:\n          \"I remember this man as the merest of striplings.\n          His father long dead now was Ecgtheow titled,\n          Him Hrethel the Geatman granted at home his\n        5 One only daughter; his battle-brave son\n          Is come but now, sought a trustworthy friend.\n          Seafaring sailors asserted it then,\n\n{Beowulf is reported to have the strength of thirty men.}\n\n          Who valuable gift-gems of the Geatmen[1] carried\n          As peace-offering thither, that he thirty men's grapple\n       10 Has in his hand, the hero-in-battle.\n\n{God hath sent him to our rescue.}\n\n          The holy Creator usward sent him,\n          To West-Dane warriors, I ween, for to render\n          'Gainst Grendel's grimness gracious assistance:\n          I shall give to the good one gift-gems for courage.\n       15 Hasten to bid them hither to speed them,[2]\n          To see assembled this circle of kinsmen;\n          Tell them expressly they're welcome in sooth to\n          The men of the Danes.\" To the door of the building\n\n[15]\n\n{Wulfgar invites the strangers in.}\n\n          Wulfgar went then, this word-message shouted:\n       20 \"My victorious liegelord bade me to tell you,\n          The East-Danes' atheling, that your origin knows he,\n          And o'er wave-billows wafted ye welcome are hither,\n          Valiant of spirit. Ye straightway may enter\n          Clad in corslets, cased in your helmets,\n       25 To see King Hrothgar. Here let your battle-boards,\n          Wood-spears and war-shafts, await your conferring.\"\n          The mighty one rose then, with many a liegeman,\n          An excellent thane-group; some there did await them,\n          And as bid of the brave one the battle-gear guarded.\n       30 Together they hied them, while the hero did guide them,\n          'Neath Heorot's roof; the high-minded went then\n          Sturdy 'neath helmet till he stood in the building.\n          Beowulf spake (his burnie did glisten,\n          His armor seamed over by the art of the craftsman):\n\n{Beowulf salutes Hrothgar, and then proceeds to boast of his youthful\nachievements.}\n\n       35 \"Hail thou, Hrothgar! I am Higelac's kinsman\n          And vassal forsooth; many a wonder\n          I dared as a stripling. The doings of Grendel,\n          In far-off fatherland I fully did know of:\n          Sea-farers tell us, this hall-building standeth,\n       40 Excellent edifice, empty and useless\n          To all the earlmen after evenlight's glimmer\n          'Neath heaven's bright hues hath hidden its glory.\n          This my earls then urged me, the most excellent of them,\n          Carles very clever, to come and assist thee,\n       45 Folk-leader Hrothgar; fully they knew of\n\n{His fight with the nickers.}\n\n          The strength of my body. Themselves they beheld me\n          When I came from the contest, when covered with gore\n          Foes I escaped from, where five[3] I had bound,\n[16]      The giant-race wasted, in the waters destroying\n       50 The nickers by night, bore numberless sorrows,\n          The Weders avenged (woes had they suffered)\n          Enemies ravaged; alone now with Grendel\n\n{He intends to fight Grendel unaided.}\n\n          I shall manage the matter, with the monster of evil,\n          The giant, decide it. Thee I would therefore\n       55 Beg of thy bounty, Bright-Danish chieftain,\n          Lord of the Scyldings, this single petition:\n          Not to refuse me, defender of warriors,\n          Friend-lord of folks, so far have I sought thee,\n          That _I_ may unaided, my earlmen assisting me,\n       60 This brave-mooded war-band, purify Heorot.\n          I have heard on inquiry, the horrible creature\n\n{Since the monster uses no weapons,}\n\n          From veriest rashness recks not for weapons;\n          I this do scorn then, so be Higelac gracious,\n          My liegelord belov�d, lenient of spirit,\n       65 To bear a blade or a broad-fashioned target,\n          A shield to the onset; only with hand-grip\n\n{I, too, shall disdain to use any.}\n\n          The foe I must grapple, fight for my life then,\n          Foeman with foeman; he fain must rely on\n          The doom of the Lord whom death layeth hold of.\n\n{Should he crush me, he will eat my companions as he has eaten thy\nthanes.}\n\n       70 I ween he will wish, if he win in the struggle,\n          To eat in the war-hall earls of the Geat-folk,\n          Boldly to swallow[4] them, as of yore he did often\n          The best of the Hrethmen! Thou needest not trouble\n          A head-watch to give me;[5] he will have me dripping\n\n[17]\n\n{In case of my defeat, thou wilt not have the trouble of burying me.}\n\n       75 And dreary with gore, if death overtake me,[6]\n          Will bear me off bleeding, biting and mouthing me,\n          The hermit will eat me, heedless of pity,\n          Marking the moor-fens; no more wilt thou need then\n\n{Should I fall, send my armor to my lord, King Higelac.}\n\n          Find me my food.[7] If I fall in the battle,\n       80 Send to Higelac the armor that serveth\n          To shield my bosom, the best of equipments,\n          Richest of ring-mails; 'tis the relic of Hrethla,\n\n{Weird is supreme}\n\n          The work of Wayland. Goes Weird as she must go!\"\n\n    [1] Some render 'gif-sceattas' by 'tribute.'--'G�ata' B. and Th.\n    emended to 'G�atum.' If this be accepted, change '_of_ the Geatmen' to\n    '_to_ the Geatmen.'\n\n    [2] If t.B.'s emendation of vv. 386, 387 be accepted, the two lines,\n    'Hasten ... kinsmen' will read: _Hasten thou, bid the throng of\n    kinsmen go into the hall together_.\n\n    [3] For 420 (_b_) and 421 (_a_), B. suggests: ��r ic (on) f�felgeban\n    ��de eotena cyn = _where I in the ocean destroyed the\n    eoten-race_.--t.B. accepts B.'s \"brilliant\" 'f�felgeban,' omits 'on,'\n    emends 'cyn' to 'h�m,' arranging: ��r ic f�felgeban ��de, eotena h�m =\n    _where I desolated the ocean, the home of the eotens_.--This would be\n    better but for changing 'cyn' to 'h�m.'--I suggest: ��r ic f�felgeband\n    (cf. nhd. Bande) ��de, eotena cyn = _where I conquered the monster\n    band, the race of the eotens_. This makes no change except to read\n    '_f�fel_' for '_f�fe_.'\n\n    [4] 'Unforhte' (444) is much disputed.--H.-So. wavers between adj. and\n    adv. Gr. and B. take it as an adv. modifying _etan: Will eat the Geats\n    fearlessly_.--Kl. considers this reading absurd, and proposes\n    'anforhte' = timid.--Understanding 'unforhte' as an adj. has this\n    advantage, viz. that it gives a parallel to 'Ge�tena le�de': but to\n    take it as an adv. is more natural. Furthermore, to call the Geats\n    'brave' might, at this point, seem like an implied thrust at the\n    Danes, so long helpless; while to call his own men 'timid' would be\n    befouling his own nest.\n\n    [5] For 'head-watch,' cf. H.-So. notes and cf. v. 2910.--Th.\n    translates: _Thou wilt not need my head to hide_ (i.e., thou wilt have\n    no occasion to bury me, as Grendel will devour me whole).--Simrock\n    imagines a kind of dead-watch.--Dr. H. Wood suggests: _Thou wilt not\n    have to bury so much as my head_ (for Grendel will be a thorough\n    undertaker),--grim humor.\n\n    [6] S. proposes a colon after 'nime�' (l. 447). This would make no\n    essential change in the translation.\n\n    [7] Owing to the vagueness of 'feorme' (451), this passage is\n    variously translated. In our translation, H.-So.'s glossary has been\n    quite closely followed. This agrees substantially with B.'s\n    translation (P. and B. XII. 87). R. translates: _Thou needst not take\n    care longer as to the consumption of my dead body._ 'L�c' is also a\n    crux here, as it may mean living body or dead body.\n\n\n\n\nVIII.\n\nHROTHGAR AND BEOWULF.--_Continued_.\n\n\n{Hrothgar responds.}\n\n          Hrothgar discoursed, helm of the Scyldings:\n          \"To defend our folk and to furnish assistance,[1]\n          Thou soughtest us hither, good friend Beowulf.\n\n{Reminiscences of Beowulf's father, Ecgtheow.}\n\n          The fiercest of feuds thy father engaged in,\n        5 Heatholaf killed he in hand-to-hand conflict\n          'Mid Wilfingish warriors; then the Wederish people\n          For fear of a feud were forced to disown him.\n          Thence flying he fled to the folk of the South-Danes,\n[18]      The race of the Scyldings, o'er the roll of the waters;\n       10 I had lately begun then to govern the Danemen,\n          The hoard-seat of heroes held in my youth,\n          Rich in its jewels: dead was Heregar,\n          My kinsman and elder had earth-joys forsaken,\n          Healfdene his bairn. He was better than I am!\n       15 That feud thereafter for a fee I compounded;\n          O'er the weltering waters to the Wilfings I sent\n          Ornaments old; oaths did he swear me.\n\n{Hrothgar recounts to Beowulf the horrors of Grendel's persecutions.}\n\n          It pains me in spirit to any to tell it,\n          What grief in Heorot Grendel hath caused me,\n       20 What horror unlooked-for, by hatred unceasing.\n          Waned is my war-band, wasted my hall-troop;\n          Weird hath offcast them to the clutches of Grendel.\n          God can easily hinder the scather\n          From deeds so direful. Oft drunken with beer\n\n{My thanes have made many boasts, but have not executed them.}\n\n       25 O'er the ale-vessel promised warriors in armor\n          They would willingly wait on the wassailing-benches\n          A grapple with Grendel, with grimmest of edges.\n          Then this mead-hall at morning with murder was reeking,\n          The building was bloody at breaking of daylight,\n       30 The bench-deals all flooded, dripping and bloodied,\n          The folk-hall was gory: I had fewer retainers,\n          Dear-beloved warriors, whom death had laid hold of.\n\n{Sit down to the feast, and give us comfort.}\n\n          Sit at the feast now, thy intents unto heroes,[2]\n          Thy victor-fame show, as thy spirit doth urge thee!\"\n\n{A bench is made ready for Beowulf and his party.}\n\n       35 For the men of the Geats then together assembled,\n          In the beer-hall blithesome a bench was made ready;\n          There warlike in spirit they went to be seated,\n          Proud and exultant. A liegeman did service,\n[19]      Who a beaker embellished bore with decorum,\n\n{The gleeman sings}\n\n       40 And gleaming-drink poured. The gleeman sang whilom\n\n{The heroes all rejoice together.}\n\n          Hearty in Heorot; there was heroes' rejoicing,\n          A numerous war-band of Weders and Danemen.\n\n    [1] B. and S. reject the reading given in H.-So., and suggested by\n    Grtvg. B. suggests for 457-458:\n\n               w�ere-ryhtum ��, wine m�n B�owulf,\n               and for �r-stafum �sic s�htest.\n\n    This means: _From the obligations of clientage, my friend Beowulf, and\n    for assistance thou hast sought us_.--This gives coherence to\n    Hrothgar's opening remarks in VIII., and also introduces a new motive\n    for Beowulf's coming to Hrothgar's aid.\n\n    [2] _Sit now at the feast, and disclose thy purposes to the victorious\n    heroes, as thy spirit urges_.--Kl. reaches the above translation by\n    erasing the comma after 'meoto' and reading 'sige-hr��secgum.'--There\n    are other and bolder emendations and suggestions. Of these the boldest\n    is to regard 'meoto' as a verb (imperative), and read 'on s�l': _Think\n    upon gayety, etc_.--All the renderings are unsatisfactory, the one\n    given in our translation involving a zeugma.\n\n\n\n\nIX.\n\nUNFERTH TAUNTS BEOWULF.\n\n\n{Unferth, a thane of Hrothgar, is jealous of Beowulf, and undertakes to\ntwit him.}\n\n          Unferth spoke up, Ecglaf his son,\n          Who sat at the feet of the lord of the Scyldings,\n          Opened the jousting (the journey[1] of Beowulf,\n          Sea-farer doughty, gave sorrow to Unferth\n        5 And greatest chagrin, too, for granted he never\n          That any man else on earth should attain to,\n          Gain under heaven, more glory than he):\n\n{Did you take part in a swimming-match with Breca?}\n\n          \"Art thou that Beowulf with Breca did struggle,\n          On the wide sea-currents at swimming contended,\n       10 Where to humor your pride the ocean ye tried,\n\n{'Twas mere folly that actuated you both to risk your lives on the ocean.}\n\n          From vainest vaunting adventured your bodies\n          In care of the waters? And no one was able\n          Nor lief nor loth one, in the least to dissuade you\n          Your difficult voyage; then ye ventured a-swimming,\n       15 Where your arms outstretching the streams ye did cover,\n          The mere-ways measured, mixing and stirring them,\n          Glided the ocean; angry the waves were,\n          With the weltering of winter. In the water's possession,\n          Ye toiled for a seven-night; he at swimming outdid thee,\n       20 In strength excelled thee. Then early at morning\n          On the Heathoremes' shore the holm-currents tossed him,\n          Sought he thenceward the home of his fathers,\n          Beloved of his liegemen, the land of the Brondings,\n          The peace-castle pleasant, where a people he wielded,\n[20]   25 Had borough and jewels. The pledge that he made thee\n\n{Breca outdid you entirely.}\n\n          The son of Beanstan hath soothly accomplished.\n          Then I ween thou wilt find thee less fortunate issue,\n\n{Much more will Grendel outdo you, if you vie with him in prowess.}\n\n          Though ever triumphant in onset of battle,\n          A grim grappling, if Grendel thou darest\n       30 For the space of a night near-by to wait for!\"\n\n{Beowulf retaliates.}\n\n          Beowulf answered, offspring of Ecgtheow:\n          \"My good friend Unferth, sure freely and wildly,\n\n{O friend Unferth, you are fuddled with beer, and cannot talk coherently.}\n\n          Thou fuddled with beer of Breca hast spoken,\n          Hast told of his journey! A fact I allege it,\n       35 That greater strength in the waters I had then,\n          Ills in the ocean, than any man else had.\n          We made agreement as the merest of striplings\n          Promised each other (both of us then were\n\n{We simply kept an engagement made in early life.}\n\n          Younkers in years) that we yet would adventure\n       40 Out on the ocean; it all we accomplished.\n          While swimming the sea-floods, sword-blade unscabbarded\n          Boldly we brandished, our bodies expected\n          To shield from the sharks. He sure was unable\n\n{He _could_ not excel me, and I _would_ not excel him.}\n\n          To swim on the waters further than I could,\n       45 More swift on the waves, nor _would_ I from him go.\n          Then we two companions stayed in the ocean\n\n{After five days the currents separated us.}\n\n          Five nights together, till the currents did part us,\n          The weltering waters, weathers the bleakest,\n          And nethermost night, and the north-wind whistled\n       50 Fierce in our faces; fell were the billows.\n          The mere fishes' mood was mightily ruffled:\n          And there against foemen my firm-knotted corslet,\n          Hand-jointed, hardy, help did afford me;\n          My battle-sark braided, brilliantly gilded,\n\n{A horrible sea-beast attacked me, but I slew him.}\n\n       55 Lay on my bosom. To the bottom then dragged me,\n          A hateful fiend-scather, seized me and held me,\n          Grim in his grapple: 'twas granted me, nathless,\n          To pierce the monster with the point of my weapon,\n          My obedient blade; battle offcarried\n       60 The mighty mere-creature by means of my hand-blow.\n\n    [1] It has been plausibly suggested that 's��' (in 501 and in 353)\n    means 'arrival.' If so, translate the bracket: _(the arrival of\n    Beowulf, the brave seafarer, was a source of great chagrin to Unferth,\n    etc.)_.\n\n[21]\n\n\n\n\nX.\n\nBEOWULF SILENCES UNFERTH.--GLEE IS HIGH.\n\n\n          \"So ill-meaning enemies often did cause me\n          Sorrow the sorest. I served them, in quittance,\n\n{My dear sword always served me faithfully.}\n\n          With my dear-lov�d sword, as in sooth it was fitting;\n          They missed the pleasure of feasting abundantly,\n        5 Ill-doers evil, of eating my body,\n          Of surrounding the banquet deep in the ocean;\n          But wounded with edges early at morning\n          They were stretched a-high on the strand of the ocean,\n\n{I put a stop to the outrages of the sea-monsters.}\n\n          Put to sleep with the sword, that sea-going travelers\n       10 No longer thereafter were hindered from sailing\n          The foam-dashing currents. Came a light from the east,\n          God's beautiful beacon; the billows subsided,\n          That well I could see the nesses projecting,\n\n{Fortune helps the brave earl.}\n\n          The blustering crags. Weird often saveth\n       15 The undoomed hero if doughty his valor!\n          But me did it fortune[1] to fell with my weapon\n          Nine of the nickers. Of night-struggle harder\n          'Neath dome of the heaven heard I but rarely,\n          Nor of wight more woful in the waves of the ocean;\n       20 Yet I 'scaped with my life the grip of the monsters,\n\n{After that escape I drifted to Finland.}\n\n          Weary from travel. Then the waters bare me\n          To the land of the Finns, the flood with the current,\n\n{I have never heard of your doing any such bold deeds.}\n\n          The weltering waves. Not a word hath been told me\n          Of deeds so daring done by thee, Unferth,\n       25 And of sword-terror none; never hath Breca\n          At the play of the battle, nor either of you two,\n          Feat so fearless perform�d with weapons\n          Glinting and gleaming . . . . . . . . . . . .\n[22]      . . . . . . . . . . . . I utter no boasting;\n\n{You are a slayer of brothers, and will suffer damnation, wise as you may\nbe.}\n\n       30 Though with cold-blooded cruelty thou killedst thy brothers,\n          Thy nearest of kin; thou needs must in hell get\n          Direful damnation, though doughty thy wisdom.\n          I tell thee in earnest, offspring of Ecglaf,\n          Never had Grendel such numberless horrors,\n       35 The direful demon, done to thy liegelord,\n          Harrying in Heorot, if thy heart were as sturdy,\n\n{Had your acts been as brave as your words, Grendel had not ravaged your\nland so long.}\n\n          Thy mood as ferocious as thou dost describe them.\n          He hath found out fully that the fierce-burning hatred,\n          The edge-battle eager, of all of your kindred,\n       40 Of the Victory-Scyldings, need little dismay him:\n          Oaths he exacteth, not any he spares\n\n{The monster is not afraid of the Danes,}\n\n          Of the folk of the Danemen, but fighteth with pleasure,\n          Killeth and feasteth, no contest expecteth\n\n{but he will soon learn to dread the Geats.}\n\n          From Spear-Danish people. But the prowess and valor\n       45 Of the earls of the Geatmen early shall venture\n          To give him a grapple. He shall go who is able\n          Bravely to banquet, when the bright-light of morning\n\n{On the second day, any warrior may go unmolested to the mead-banquet.}\n\n          Which the second day bringeth, the sun in its ether-robes,\n          O'er children of men shines from the southward!\"\n       50 Then the gray-haired, war-famed giver of treasure\n\n{Hrothgar's spirits are revived.}\n\n          Was blithesome and joyous, the Bright-Danish ruler\n          Expected assistance; the people's protector\n\n{The old king trusts Beowulf. The heroes are joyful.}\n\n          Heard from Beowulf his bold resolution.\n          There was laughter of heroes; loud was the clatter,\n       55 The words were winsome. Wealhtheow advanced then,\n\n{Queen Wealhtheow plays the hostess.}\n\n          Consort of Hrothgar, of courtesy mindful,\n          Gold-decked saluted the men in the building,\n          And the freeborn woman the beaker presented\n\n{She offers the cup to her husband first.}\n\n          To the lord of the kingdom, first of the East-Danes,\n       60 Bade him be blithesome when beer was a-flowing,\n          Lief to his liegemen; he lustily tasted\n          Of banquet and beaker, battle-famed ruler.\n          The Helmingish lady then graciously circled\n          'Mid all the liegemen lesser and greater:\n\n[23]\n\n{She gives presents to the heroes.}\n\n       65 Treasure-cups tendered, till time was afforded\n          That the decorous-mooded, diademed folk-queen\n\n{Then she offers the cup to Beowulf, thanking God that aid has come.}\n\n          Might bear to Beowulf the bumper o'errunning;\n          She greeted the Geat-prince, God she did thank,\n          Most wise in her words, that her wish was accomplished,\n       70 That in any of earlmen she ever should look for\n          Solace in sorrow. He accepted the beaker,\n          Battle-bold warrior, at Wealhtheow's giving,\n\n{Beowulf states to the queen the object of his visit.}\n\n          Then equipped for combat quoth he in measures,\n          Beowulf spake, offspring of Ecgtheow:\n       75 \"I purposed in spirit when I mounted the ocean,\n\n{I determined to do or die.}\n\n          When I boarded my boat with a band of my liegemen,\n          I would work to the fullest the will of your people\n          Or in foe's-clutches fastened fall in the battle.\n          Deeds I shall do of daring and prowess,\n       80 Or the last of my life-days live in this mead-hall.\"\n          These words to the lady were welcome and pleasing,\n          The boast of the Geatman; with gold trappings broidered\n          Went the freeborn folk-queen her fond-lord to sit by.\n\n{Glee is high.}\n\n          Then again as of yore was heard in the building\n       85 Courtly discussion, conquerors' shouting,\n          Heroes were happy, till Healfdene's son would\n          Go to his slumber to seek for refreshing;\n          For the horrid hell-monster in the hall-building knew he\n          A fight was determined,[2] since the light of the sun they\n       90 No longer could see, and lowering darkness\n          O'er all had descended, and dark under heaven\n          Shadowy shapes came shying around them.\n\n{Hrothgar retires, leaving Beowulf in charge of the hall.}\n\n          The liegemen all rose then. One saluted the other,\n          Hrothgar Beowulf, in rhythmical measures,\n       95 Wishing him well, and, the wassail-hall giving\n          To his care and keeping, quoth he departing:\n[24]      \"Not to any one else have I ever entrusted,\n          But thee and thee only, the hall of the Danemen,\n          Since high I could heave my hand and my buckler.\n      100 Take thou in charge now the noblest of houses;\n          Be mindful of honor, exhibiting prowess,\n          Watch 'gainst the foeman! Thou shalt want no enjoyments,\n          Survive thou safely adventure so glorious!\"\n\n    [1] The repetition of 'hw��ere' (574 and 578) is regarded by some\n    scholars as a defect. B. suggests 'sw� ��r' for the first: _So there\n    it befell me, etc._ Another suggestion is to change the second\n    'hw��ere' into 'sw� ��r': _So there I escaped with my life, etc._\n\n    [2] Kl. suggests a period after 'determined.' This would give the\n    passage as follows: _Since they no longer could see the light of the\n    sun, and lowering darkness was down over all, dire under the heavens\n    shadowy beings came going around them_.\n\n\n\n\nXI.\n\nALL SLEEP SAVE ONE.\n\n\n{Hrothgar retires.}\n\n          Then Hrothgar departed, his earl-throng attending him,\n          Folk-lord of Scyldings, forth from the building;\n          The war-chieftain wished then Wealhtheow to look for,\n          The queen for a bedmate. To keep away Grendel\n\n{God has provided a watch for the hall.}\n\n        5 The Glory of Kings had given a hall-watch,\n          As men heard recounted: for the king of the Danemen\n          He did special service, gave the giant a watcher:\n          And the prince of the Geatmen implicitly trusted\n\n{Beowulf is self-confident}\n\n          His warlike strength and the Wielder's protection.\n\n{He prepares for rest.}\n\n       10 His armor of iron off him he did then,\n          His helmet from his head, to his henchman committed\n          His chased-handled chain-sword, choicest of weapons,\n          And bade him bide with his battle-equipments.\n          The good one then uttered words of defiance,\n       15 Beowulf Geatman, ere his bed he upmounted:\n\n{Beowulf boasts of his ability to cope with Grendel.}\n\n          \"I hold me no meaner in matters of prowess,\n          In warlike achievements, than Grendel does himself;\n          Hence I seek not with sword-edge to sooth him to slumber,\n          Of life to bereave him, though well I am able.\n\n{We will fight with nature's weapons only.}\n\n       20 No battle-skill[1] has he, that blows he should strike me,\n          To shatter my shield, though sure he is mighty\n[25]      In strife and destruction; but struggling by night we\n          Shall do without edges, dare he to look for\n          Weaponless warfare, and wise-mooded Father\n       25 The glory apportion, God ever-holy,\n\n{God may decide who shall conquer}\n\n          On which hand soever to him seemeth proper.\"\n          Then the brave-mooded hero bent to his slumber,\n          The pillow received the cheek of the noble;\n\n{The Geatish warriors lie down.}\n\n          And many a martial mere-thane attending\n       30 Sank to his slumber. Seemed it unlikely\n\n{They thought it very unlikely that they should ever see their homes\nagain.}\n\n          That ever thereafter any should hope to\n          Be happy at home, hero-friends visit\n          Or the lordly troop-castle where he lived from his childhood;\n          They had heard how slaughter had snatched from the wine-hall,\n       35 Had recently ravished, of the race of the Scyldings\n\n{But God raised up a deliverer.}\n\n          Too many by far. But the Lord to them granted\n          The weaving of war-speed, to Wederish heroes\n          Aid and comfort, that every opponent\n          By one man's war-might they worsted and vanquished,\n\n{God rules the world.}\n\n       40 By the might of himself; the truth is established\n          That God Almighty hath governed for ages\n          Kindreds and nations. A night very lurid\n\n{Grendel comes to Heorot.}\n\n          The trav'ler-at-twilight came tramping and striding.\n          The warriors were sleeping who should watch the horned-building,\n\n{Only one warrior is awake.}\n\n       45 One only excepted. 'Mid earthmen 'twas 'stablished,\n          Th' implacable foeman was powerless to hurl them\n          To the land of shadows, if the Lord were unwilling;\n          But serving as warder, in terror to foemen,\n          He angrily bided the issue of battle.[2]\n\n    [1] Gr. understood 'g�dra' as meaning 'advantages in battle.' This\n    rendering H.-So. rejects. The latter takes the passage as meaning that\n    Grendel, though mighty and formidable, has no skill in the art of war.\n\n    [2] B. in his masterly articles on Beowulf (P. and B. XII.) rejects\n    the division usually made at this point, '��.' (711), usually rendered\n    'then,' he translates 'when,' and connects its clause with the\n    foregoing sentence. These changes he makes to reduce the number of\n    'c�m's' as principal verbs. (Cf. 703, 711, 721.) With all deference to\n    this acute scholar, I must say that it seems to me that the poet is\n    exhausting his resources to bring out clearly the supreme event on\n    which the whole subsequent action turns. First, he (Grendel) came _in\n    the wan night_; second, he came _from the moor_; third, he came _to\n    the hall_. Time, place from which, place to which, are all given.\n\n[26]\n\n\n\n\nXII.\n\nGRENDEL AND BEOWULF.\n\n\n{Grendel comes from the fens.}\n\n          'Neath the cloudy cliffs came from the moor then\n          Grendel going, God's anger bare he.\n          The monster intended some one of earthmen\n          In the hall-building grand to entrap and make way with:\n\n{He goes towards the joyous building.}\n\n        5 He went under welkin where well he knew of\n          The wine-joyous building, brilliant with plating,\n          Gold-hall of earthmen. Not the earliest occasion\n\n{This was not his first visit there.}\n\n          He the home and manor of Hrothgar had sought:\n          Ne'er found he in life-days later nor earlier\n       10 Hardier hero, hall-thanes[1] more sturdy!\n          Then came to the building the warrior marching,\n\n{His horrid fingers tear the door open.}\n\n          Bereft of his joyance. The door quickly opened\n          On fire-hinges fastened, when his fingers had touched it;\n          The fell one had flung then--his fury so bitter--\n       15 Open the entrance. Early thereafter\n          The foeman trod the shining hall-pavement,\n\n{He strides furiously into the hall.}\n\n          Strode he angrily; from the eyes of him glimmered\n          A lustre unlovely likest to fire.\n          He beheld in the hall the heroes in numbers,\n       20 A circle of kinsmen sleeping together,\n\n{He exults over his supposed prey.}\n\n          A throng of thanemen: then his thoughts were exultant,\n          He minded to sunder from each of the thanemen\n          The life from his body, horrible demon,\n          Ere morning came, since fate had allowed him\n\n{Fate has decreed that he shall devour no more heroes. Beowulf suffers\nfrom suspense.}\n\n       25 The prospect of plenty. Providence willed not\n          To permit him any more of men under heaven\n          To eat in the night-time. Higelac's kinsman\n          Great sorrow endured how the dire-mooded creature\n[27]      In unlooked-for assaults were likely to bear him.\n       30 No thought had the monster of deferring the matter,\n\n{Grendel immediately seizes a sleeping warrior, and devours him.}\n\n          But on earliest occasion he quickly laid hold of\n          A soldier asleep, suddenly tore him,\n          Bit his bone-prison, the blood drank in currents,\n          Swallowed in mouthfuls: he soon had the dead man's\n       35 Feet and hands, too, eaten entirely.\n          Nearer he strode then, the stout-hearted warrior\n\n{Beowulf and Grendel grapple.}\n\n          Snatched as he slumbered, seizing with hand-grip,\n          Forward the foeman foined with his hand;\n          Caught he quickly the cunning deviser,\n       40 On his elbow he rested. This early discovered\n          The master of malice, that in middle-earth's regions,\n          'Neath the whole of the heavens, no hand-grapple greater\n\n{The monster is amazed at Beowulf's strength.}\n\n          In any man else had he ever encountered:\n          Fearful in spirit, faint-mooded waxed he,\n       45 Not off could betake him; death he was pondering,\n\n{He is anxious to flee.}\n\n          Would fly to his covert, seek the devils' assembly:\n          His calling no more was the same he had followed\n          Long in his lifetime. The liege-kinsman worthy\n\n{Beowulf recalls his boast of the evening, and determines to fulfil it.}\n\n          Of Higelac minded his speech of the evening,\n       50 Stood he up straight and stoutly did seize him.\n          His fingers crackled; the giant was outward,\n          The earl stepped farther. The famous one minded\n          To flee away farther, if he found an occasion,\n          And off and away, avoiding delay,\n       55 To fly to the fen-moors; he fully was ware of\n          The strength of his grapple in the grip of the foeman.\n\n{'Twas a luckless day for Grendel.}\n\n          'Twas an ill-taken journey that the injury-bringing,\n          Harrying harmer to Heorot wandered:\n\n{The hall groans.}\n\n          The palace re-echoed; to all of the Danemen,\n       60 Dwellers in castles, to each of the bold ones,\n          Earlmen, was terror. Angry they both were,\n          Archwarders raging.[2] Rattled the building;\n[28]      'Twas a marvellous wonder that the wine-hall withstood then\n          The bold-in-battle, bent not to earthward,\n       65 Excellent earth-hall; but within and without it\n          Was fastened so firmly in fetters of iron,\n          By the art of the armorer. Off from the sill there\n          Bent mead-benches many, as men have informed me,\n          Adorned with gold-work, where the grim ones did struggle.\n       70 The Scylding wise men weened ne'er before\n          That by might and main-strength a man under heaven\n          Might break it in pieces, bone-decked, resplendent,\n          Crush it by cunning, unless clutch of the fire\n          In smoke should consume it. The sound mounted upward\n\n{Grendel's cries terrify the Danes.}\n\n       75 Novel enough; on the North Danes fastened\n          A terror of anguish, on all of the men there\n          Who heard from the wall the weeping and plaining,\n          The song of defeat from the foeman of heaven,\n          Heard him hymns of horror howl, and his sorrow\n       80 Hell-bound bewailing. He held him too firmly\n          Who was strongest of main-strength of men of that era.\n\n    [1] B. and t.B. emend so as to make lines 9 and 10 read: _Never in his\n    life, earlier or later, had he, the hell-thane, found a braver\n    hero_.--They argue that Beowulf's companions had done nothing to merit\n    such encomiums as the usual readings allow them.\n\n    [2] For 'r��e r�n-weardas' (771), t.B. suggests 'r��e, r�nhearde.'\n    Translate: _They were both angry, raging and mighty_.\n\n\n\n\nXIII.\n\nGRENDEL IS VANQUISHED.\n\n\n{Beowulf has no idea of letting Grendel live.}\n\n          For no cause whatever would the earlmen's defender\n          Leave in life-joys the loathsome newcomer,\n          He deemed his existence utterly useless\n          To men under heaven. Many a noble\n        5 Of Beowulf brandished his battle-sword old,\n          Would guard the life of his lord and protector,\n          The far-famous chieftain, if able to do so;\n          While waging the warfare, this wist they but little,\n          Brave battle-thanes, while his body intending\n\n{No weapon would harm Grendel; he bore a charmed life.}\n\n       10 To slit into slivers, and seeking his spirit:\n          That the relentless foeman nor finest of weapons\n          Of all on the earth, nor any of war-bills\n[29]      Was willing to injure; but weapons of victory\n          Swords and suchlike he had sworn to dispense with.\n       15 His death at that time must prove to be wretched,\n          And the far-away spirit widely should journey\n          Into enemies' power. This plainly he saw then\n          Who with mirth[1] of mood malice no little\n          Had wrought in the past on the race of the earthmen\n       20 (To God he was hostile), that his body would fail him,\n          But Higelac's hardy henchman and kinsman\n          Held him by the hand; hateful to other\n\n{Grendel is sorely wounded.}\n\n          Was each one if living. A body-wound suffered\n          The direful demon, damage incurable\n\n{His body bursts.}\n\n       25 Was seen on his shoulder, his sinews were shivered,\n          His body did burst. To Beowulf was given\n          Glory in battle; Grendel from thenceward\n          Must flee and hide him in the fen-cliffs and marshes,\n          Sick unto death, his dwelling must look for\n       30 Unwinsome and woful; he wist the more fully\n\n{The monster flees away to hide in the moors.}\n\n          The end of his earthly existence was nearing,\n          His life-days' limits. At last for the Danemen,\n          When the slaughter was over, their wish was accomplished.\n          The comer-from-far-land had cleansed then of evil,\n       35 Wise and valiant, the war-hall of Hrothgar,\n          Saved it from violence. He joyed in the night-work,\n          In repute for prowess; the prince of the Geatmen\n          For the East-Danish people his boast had accomplished,\n          Bettered their burdensome bale-sorrows fully,\n       40 The craft-begot evil they erstwhile had suffered\n          And were forced to endure from crushing oppression,\n          Their manifold misery. 'Twas a manifest token,\n\n{Beowulf suspends Grendel's hand and arm in Heorot.}\n\n          When the hero-in-battle the hand suspended,\n          The arm and the shoulder (there was all of the claw\n       45 Of Grendel together) 'neath great-stretching hall-roof.\n\n    [1] It has been proposed to translate 'myr�e' by _with sorrow_; but\n    there seems no authority for such a rendering. To the present\n    translator, the phrase 'm�des myr�e' seems a mere padding for\n    _gladly_; i.e., _he who gladly harassed mankind_.\n\n[30]\n\n\n\n\nXIV.\n\nREJOICING OF THE DANES.\n\n\n{At early dawn, warriors from far and near come together to hear of the\nnight's adventures.}\n\n          In the mist of the morning many a warrior\n          Stood round the gift-hall, as the story is told me:\n          Folk-princes fared then from far and from near\n          Through long-stretching journeys to look at the wonder,\n        5 The footprints of the foeman. Few of the warriors\n\n{Few warriors lamented Grendel's destruction.}\n\n          Who gazed on the foot-tracks of the inglorious creature\n          His parting from life pained very deeply,\n          How, weary in spirit, off from those regions\n          In combats conquered he carried his traces,\n       10 Fated and flying, to the flood of the nickers.\n\n{Grendel's blood dyes the waters.}\n\n          There in bloody billows bubbled the currents,\n          The angry eddy was everywhere mingled\n          And seething with gore, welling with sword-blood;[1]\n          He death-doomed had hid him, when reaved of his joyance\n       15 He laid down his life in the lair he had fled to,\n          His heathenish spirit, where hell did receive him.\n          Thence the friends from of old backward turned them,\n          And many a younker from merry adventure,\n          Striding their stallions, stout from the seaward,\n       20 Heroes on horses. There were heard very often\n\n{Beowulf is the hero of the hour.}\n\n          Beowulf's praises; many often asserted\n          That neither south nor north, in the circuit of waters,\n\n{He is regarded as a probable successor to Hrothgar.}\n\n          O'er outstretching earth-plain, none other was better\n          'Mid bearers of war-shields, more worthy to govern,\n       25 'Neath the arch of the ether. Not any, however,\n          'Gainst the friend-lord muttered, mocking-words uttered\n\n{But no word is uttered to derogate from the old king}\n\n          Of Hrothgar the gracious (a good king he).\n          Oft the famed ones permitted their fallow-skinned horses\n[31]      To run in rivalry, racing and chasing,\n       30 Where the fieldways appeared to them fair and inviting,\n          Known for their excellence; oft a thane of the folk-lord,[2]\n\n{The gleeman sings the deeds of heroes.}\n\n          [3]A man of celebrity, mindful of rhythms,\n          Who ancient traditions treasured in memory,\n          New word-groups found properly bound:\n       35 The bard after 'gan then Beowulf's venture\n\n{He sings in alliterative measures of Beowulf's prowess.}\n\n          Wisely to tell of, and words that were clever\n          To utter skilfully, earnestly speaking,\n          Everything told he that he heard as to Sigmund's\n\n{Also of Sigemund, who has slain a great fire-dragon.}\n\n          Mighty achievements, many things hidden,\n       40 The strife of the W�lsing, the wide-going ventures\n          The children of men knew of but little,\n          The feud and the fury, but Fitela with him,\n          When suchlike matters he minded to speak of,\n          Uncle to nephew, as in every contention\n       45 Each to other was ever devoted:\n          A numerous host of the race of the scathers\n          They had slain with the sword-edge. To Sigmund accrued then\n          No little of glory, when his life-days were over,\n          Since he sturdy in struggle had destroyed the great dragon,\n       50 The hoard-treasure's keeper; 'neath the hoar-grayish stone he,\n          The son of the atheling, unaided adventured\n          The perilous project; not present was Fitela,\n          Yet the fortune befell him of forcing his weapon\n          Through the marvellous dragon, that it stood in the wall,\n       55 Well-honored weapon; the worm was slaughtered.\n          The great one had gained then by his glorious achievement\n          To reap from the ring-hoard richest enjoyment,\n[32]      As best it did please him: his vessel he loaded,\n          Shining ornaments on the ship's bosom carried,\n       60 Kinsman of W�ls: the drake in heat melted.\n\n{Sigemund was widely famed.}\n\n          He was farthest famed of fugitive pilgrims,\n          Mid wide-scattered world-folk, for works of great prowess,\n          War-troopers' shelter: hence waxed he in honor.[4]\n\n{Heremod, an unfortunate Danish king, is introduced by way of contrast.}\n\n          Afterward Heremod's hero-strength failed him,\n       65 His vigor and valor. 'Mid venomous haters\n          To the hands of foemen he was foully delivered,\n          Offdriven early. Agony-billows\n\n{Unlike Sigemund and Beowulf, Heremod was a burden to his people.}\n\n          Oppressed him too long, to his people he became then,\n          To all the athelings, an ever-great burden;\n       70 And the daring one's journey in days of yore\n          Many wise men were wont to deplore,\n          Such as hoped he would bring them help in their sorrow,\n          That the son of their ruler should rise into power,\n          Holding the headship held by his fathers,\n       75 Should govern the people, the gold-hoard and borough,\n          The kingdom of heroes, the realm of the Scyldings.\n\n{Beowulf is an honor to his race.}\n\n          He to all men became then far more beloved,\n          Higelac's kinsman, to kindreds and races,\n          To his friends much dearer; him malice assaulted.--\n\n{The story is resumed.}\n\n       80 Oft running and racing on roadsters they measured\n          The dun-colored highways. Then the light of the morning\n          Was hurried and hastened. Went henchmen in numbers\n          To the beautiful building, bold ones in spirit,\n          To look at the wonder; the liegelord himself then\n       85 From his wife-bower wending, warden of treasures,\n          Glorious trod with troopers unnumbered,\n          Famed for his virtues, and with him the queen-wife\n          Measured the mead-ways, with maidens attending.\n\n    [1] S. emends, suggesting 'd�op' for 'd�og,' and removing semicolon\n    after 'w�ol.' The two half-lines 'welling ... hid him' would then\n    read: _The bloody deep welled with sword-gore_. B. accepts 'd�op' for\n    'd�og,' but reads 'd�a�-f�ges': _The deep boiled with the sword-gore\n    of the death-doomed one_.\n\n    [2] Another and quite different rendering of this passage is as\n    follows: _Oft a liegeman of the king, a fame-covered man mindful of\n    songs, who very many ancient traditions remembered (he found other\n    word-groups accurately bound together) began afterward to tell of\n    Beowulf's adventure, skilfully to narrate it, etc_.\n\n    [3] Might 'guma gilp-hladen' mean 'a man laden with boasts of the\n    deeds of others'?\n\n    [4] t.B. accepts B.'s 'h� ��s �ron ��h' as given by H.-So., but puts a\n    comma after '��h,' and takes 'si��an' as introducing a dependent\n    clause: _He throve in honor since Heremod's strength ... had\n    decreased_.\n\n[33]\n\n\n\n\nXV.\n\nHROTHGAR'S GRATITUDE.\n\n\n          Hrothgar discoursed (to the hall-building went he,\n          He stood by the pillar,[1] saw the steep-rising hall-roof\n          Gleaming with gold-gems, and Grendel his hand there):\n\n{Hrothgar gives thanks for the overthrow of the monster.}\n\n          \"For the sight we behold now, thanks to the Wielder\n        5 Early be offered! Much evil I bided,\n          Snaring from Grendel:[2] God can e'er 'complish\n          Wonder on wonder, Wielder of Glory!\n\n{I had given up all hope, when this brave liegeman came to our aid.}\n\n          But lately I reckoned ne'er under heaven\n          Comfort to gain me for any of sorrows,\n       10 While the handsomest of houses horrid with bloodstain\n          Gory uptowered; grief had offfrightened[3]\n          Each of the wise ones who weened not that ever\n          The folk-troop's defences 'gainst foes they should strengthen,\n          'Gainst sprites and monsters. Through the might of the Wielder\n       15 A doughty retainer hath a deed now accomplished\n          Which erstwhile we all with our excellent wisdom\n\n{If his mother yet liveth, well may she thank God for this son.}\n\n          Failed to perform. May affirm very truly\n          What woman soever in all of the nations\n          Gave birth to the child, if yet she surviveth,\n       20 That the long-ruling Lord was lavish to herward\n          In the birth of the bairn. Now, Beowulf dear,\n\n{Hereafter, Beowulf, thou shalt be my son.}\n\n          Most excellent hero, I'll love thee in spirit\n          As bairn of my body; bear well henceforward\n          The relationship new. No lack shall befall thee\n       25 Of earth-joys any I ever can give thee.\n          Full often for lesser service I've given\n[34]      Hero less hardy hoard-treasure precious,\n\n{Thou hast won immortal distinction.}\n\n          To a weaker in war-strife. By works of distinction\n          Thou hast gained for thyself now that thy glory shall flourish\n       30 Forever and ever. The All-Ruler quite thee\n          With good from His hand as He hitherto did thee!\"\n\n{Beowulf replies: I was most happy to render thee this service.}\n\n          Beowulf answered, Ecgtheow's offspring:\n          \"That labor of glory most gladly achieved we,\n          The combat accomplished, unquailing we ventured\n       35 The enemy's grapple; I would grant it much rather\n          Thou wert able to look at the creature in person,\n          Faint unto falling, the foe in his trappings!\n          On murder-bed quickly I minded to bind him,\n          With firm-holding fetters, that forced by my grapple\n       40 Low he should lie in life-and-death struggle\n          'Less his body escape; I was wholly unable,\n\n{I could not keep the monster from escaping, as God did not will that I\nshould.}\n\n          Since God did not will it, to keep him from going,\n          Not held him that firmly, hated opposer;\n          Too swift was the foeman. Yet safety regarding\n       45 He suffered his hand behind him to linger,\n          His arm and shoulder, to act as watcher;\n\n{He left his hand and arm behind.}\n\n          No shadow of solace the woe-begone creature\n          Found him there nathless: the hated destroyer\n          Liveth no longer, lashed for his evils,\n       50 But sorrow hath seized him, in snare-meshes hath him\n          Close in its clutches, keepeth him writhing\n          In baleful bonds: there banished for evil\n          The man shall wait for the mighty tribunal,\n\n{God will give him his deserts.}\n\n          How the God of glory shall give him his earnings.\"\n       55 Then the soldier kept silent, son of old Ecglaf,\n\n{Unferth has nothing more to say, for Beowulf's actions speak louder than\nwords.}\n\n          From boasting and bragging of battle-achievements,\n          Since the princes beheld there the hand that depended\n          'Neath the lofty hall-timbers by the might of the nobleman,\n          Each one before him, the enemy's fingers;\n       60 Each finger-nail strong steel most resembled,\n          The heathen one's hand-spur, the hero-in-battle's\n          Claw most uncanny; quoth they agreeing,\n\n[35]\n\n{No sword will harm the monster.}\n\n          That not any excellent edges of brave ones\n          Was willing to touch him, the terrible creature's\n       65 Battle-hand bloody to bear away from him.\n\n    [1] B. and t.B. read 'sta�ole,' and translate _stood on the floor_.\n\n    [2] For 'snaring from Grendel,' 'sorrows at Grendel's hands' has been\n    suggested. This gives a parallel to 'l��es.' 'Grynna' may well be gen.\n    pl. of 'gyrn,' by a scribal slip.\n\n    [3] The H.-So punctuation has been followed; but B. has been followed\n    in understanding 'gehwylcne' as object of 'w�d-scofen (h�fde).' Gr.\n    construes 'w�a' as nom abs.\n\n\n\n\nXVI.\n\nHROTHGAR LAVISHES GIFTS UPON HIS DELIVERER.\n\n\n{Heorot is adorned with hands.}\n\n          Then straight was ordered that Heorot inside[1]\n          With hands be embellished: a host of them gathered,\n          Of men and women, who the wassailing-building\n          The guest-hall begeared. Gold-flashing sparkled\n        5 Webs on the walls then, of wonders a many\n          To each of the heroes that look on such objects.\n\n{The hall is defaced, however.}\n\n          The beautiful building was broken to pieces\n          Which all within with irons was fastened,\n          Its hinges torn off: only the roof was\n       10 Whole and uninjured when the horrible creature\n          Outlawed for evil off had betaken him,\n          Hopeless of living. 'Tis hard to avoid it\n\n{[A vague passage of five verses.]}\n\n          (Whoever will do it!); but he doubtless must come to[2]\n          The place awaiting, as Wyrd hath appointed,\n       15 Soul-bearers, earth-dwellers, earls under heaven,\n          Where bound on its bed his body shall slumber\n\n{Hrothgar goes to the banquet.}\n\n          When feasting is finished. Full was the time then\n          That the son of Healfdene went to the building;\n[36]      The excellent atheling would eat of the banquet.\n       20 Ne'er heard I that people with hero-band larger\n          Bare them better tow'rds their bracelet-bestower.\n          The laden-with-glory stooped to the bench then\n          (Their kinsmen-companions in plenty were joyful,\n          Many a cupful quaffing complaisantly),\n       25 Doughty of spirit in the high-tow'ring palace,\n\n{Hrothgar's nephew, Hrothulf, is present.}\n\n          Hrothgar and Hrothulf. Heorot then inside\n          Was filled with friendly ones; falsehood and treachery\n          The Folk-Scyldings now nowise did practise.\n\n{Hrothgar lavishes gifts upon Beowulf.}\n\n          Then the offspring of Healfdene offered to Beowulf\n       30 A golden standard, as reward for the victory,\n          A banner embossed, burnie and helmet;\n          Many men saw then a song-famous weapon\n          Borne 'fore the hero. Beowulf drank of\n          The cup in the building; that treasure-bestowing\n       35 He needed not blush for in battle-men's presence.\n\n{Four handsomer gifts were never presented.}\n\n          Ne'er heard I that many men on the ale-bench\n          In friendlier fashion to their fellows presented\n          Four bright jewels with gold-work embellished.\n          'Round the roof of the helmet a head-guarder outside\n       40 Braided with wires, with bosses was furnished,\n          That swords-for-the-battle fight-hardened might fail\n          Boldly to harm him, when the hero proceeded\n\n{Hrothgar commands that eight finely caparisoned steeds be brought to\nBeowulf.}\n\n          Forth against foemen. The defender of earls then\n          Commanded that eight steeds with bridles\n       45 Gold-plated, gleaming, be guided to hallward,\n          Inside the building; on one of them stood then\n          An art-broidered saddle embellished with jewels;\n          'Twas the sovereign's seat, when the son of King Healfdene\n          Was pleased to take part in the play of the edges;\n       50 The famous one's valor ne'er failed at the front when\n          Slain ones were bowing. And to Beowulf granted\n          The prince of the Ingwins, power over both,\n          O'er war-steeds and weapons; bade him well to enjoy them.\n          In so manly a manner the mighty-famed chieftain,\n[37]   55 Hoard-ward of heroes, with horses and jewels\n          War-storms requited, that none e'er condemneth\n          Who willeth to tell truth with full justice.\n\n    [1] Kl. suggests 'hroden' for 'h�ten,' and renders: _Then quickly was\n    Heorot adorned within, with hands bedecked_.--B. suggests 'gefr�twon'\n    instead of 'gefr�twod,' and renders: _Then was it commanded to adorn\n    Heorot within quickly with hands_.--The former has the advantage of\n    affording a parallel to 'gefr�twod': both have the disadvantage of\n    altering the text.\n\n    [2] The passage 1005-1009 seems to be hopeless. One difficult point is\n    to find a subject for 'gesacan.' Some say 'he'; others supply 'each,'\n    _i.e., every soul-bearer ... must gain the inevitable place_. The\n    genitives in this case are partitive.--If 'he' be subj., the genitives\n    are dependent on 'gearwe' (= prepared).--The 'he' itself is disputed,\n    some referring it to Grendel; but B. takes it as involved in the\n    parenthesis.\n\n\n\n\nXVII.\n\nBANQUET (_continued_).--THE SCOP'S SONG OF FINN AND HN�F.\n\n\n{Each of Beowulf's companions receives a costly gift.}\n\n          And the atheling of earlmen to each of the heroes\n          Who the ways of the waters went with Beowulf,\n          A costly gift-token gave on the mead-bench,\n          Offered an heirloom, and ordered that that man\n\n{The warrior killed by Grendel is to be paid for in gold.}\n\n        5 With gold should be paid for, whom Grendel had erstwhile\n          Wickedly slaughtered, as he more of them had done\n          Had far-seeing God and the mood of the hero\n          The fate not averted: the Father then governed\n          All of the earth-dwellers, as He ever is doing;\n       10 Hence insight for all men is everywhere fittest,\n          Forethought of spirit! much he shall suffer\n          Of lief and of loathsome who long in this present\n          Useth the world in this woful existence.\n          There was music and merriment mingling together\n\n{Hrothgar's scop recalls events in the reign of his lord's father.}\n\n       15 Touching Healfdene's leader; the joy-wood was fingered,\n          Measures recited, when the singer of Hrothgar\n          On mead-bench should mention the merry hall-joyance\n          Of the kinsmen of Finn, when onset surprised them:\n\n{Hn�f, the Danish general, is treacherously attacked while staying at\nFinn's castle.}\n\n          \"The Half-Danish hero, Hn�f of the Scyldings,\n       20 On the field of the Frisians was fated to perish.\n          Sure Hildeburg needed not mention approving\n          The faith of the Jutemen: though blameless entirely,\n\n{Queen Hildeburg is not only wife of Finn, but a kinswoman of the murdered\nHn�f.}\n\n          When shields were shivered she was shorn of her darlings,\n          Of bairns and brothers: they bent to their fate\n       25 With war-spear wounded; woe was that woman.\n          Not causeless lamented the daughter of Hoce\n          The decree of the Wielder when morning-light came and\n          She was able 'neath heaven to behold the destruction\n[38]      Of brothers and bairns, where the brightest of earth-joys\n\n{Finn's force is almost exterminated.}\n\n       30 She had hitherto had: all the henchmen of Finn\n          War had offtaken, save a handful remaining,\n          That he nowise was able to offer resistance[1]\n\n{Hengest succeeds Hn�f as Danish general.}\n\n          To the onset of Hengest in the parley of battle,\n          Nor the wretched remnant to rescue in war from\n       35 The earl of the atheling; but they offered conditions,\n\n{Compact between the Frisians and the Danes.}\n\n          Another great building to fully make ready,\n          A hall and a high-seat, that half they might rule with\n          The sons of the Jutemen, and that Folcwalda's son would\n          Day after day the Danemen honor\n       40 When gifts were giving, and grant of his ring-store\n          To Hengest's earl-troop ever so freely,\n          Of his gold-plated jewels, as he encouraged the Frisians\n\n{Equality of gifts agreed on.}\n\n          On the bench of the beer-hall. On both sides they swore then\n          A fast-binding compact; Finn unto Hengest\n       45 With no thought of revoking vowed then most solemnly\n          The woe-begone remnant well to take charge of,\n          His Witan advising; the agreement should no one\n          By words or works weaken and shatter,\n          By artifice ever injure its value,\n       50 Though reaved of their ruler their ring-giver's slayer\n          They followed as vassals, Fate so requiring:\n\n{No one shall refer to old grudges.}\n\n          Then if one of the Frisians the quarrel should speak of\n          In tones that were taunting, terrible edges\n          Should cut in requital. Accomplished the oath was,\n       55 And treasure of gold from the hoard was uplifted.\n\n{Danish warriors are burned on a funeral-pyre.}\n\n          The best of the Scylding braves was then fully\n          Prepared for the pile; at the pyre was seen clearly\n          The blood-gory burnie, the boar with his gilding,\n          The iron-hard swine, athelings many\n       60 Fatally wounded; no few had been slaughtered.\n          Hildeburg bade then, at the burning of Hn�f,\n\n[39]\n\n{Queen Hildeburg has her son burnt along with Hn�f.}\n\n          The bairn of her bosom to bear to the fire,\n          That his body be burned and borne to the pyre.\n          The woe-stricken woman wept on his shoulder,[2]\n       65 In measures lamented; upmounted the hero.[3]\n          The greatest of dead-fires curled to the welkin,\n          On the hill's-front crackled; heads were a-melting,\n          Wound-doors bursting, while the blood was a-coursing\n          From body-bite fierce. The fire devoured them,\n       70 Greediest of spirits, whom war had offcarried\n          From both of the peoples; their bravest were fallen.\n\n    [1] For 1084, R. suggests 'wiht Hengeste wi� gefeohtan.'--K. suggests\n    'wi� Hengeste wiht gefeohtan.' Neither emendation would make any\n    essential change in the translation.\n\n    [2] The separation of adjective and noun by a phrase (cf. v. 1118)\n    being very unusual, some scholars have put 'earme on eaxle' with the\n    foregoing lines, inserting a semicolon after 'eaxle.' In this case 'on\n    eaxe' (_i.e._, on the ashes, cinders) is sometimes read, and this\n    affords a parallel to 'on b�l.' Let us hope that a satisfactory\n    rendering shall yet be reached without resorting to any tampering with\n    the text, such as Lichtenheld proposed: 'earme ides on eaxle\n    gnornode.'\n\n    [3] For 'g��-rinc,' 'g��-r�c,' _battle-smoke_, has been suggested.\n\n\n\n\nXVIII.\n\nTHE FINN EPISODE (_continued_).--THE BANQUET CONTINUES.\n\n\n{The survivors go to Friesland, the home of Finn.}\n\n          \"Then the warriors departed to go to their dwellings,\n          Reaved of their friends, Friesland to visit,\n          Their homes and high-city. Hengest continued\n\n{Hengest remains there all winter, unable to get away.}\n\n          Biding with Finn the blood-tainted winter,\n        5 Wholly unsundered;[1] of fatherland thought he\n          Though unable to drive the ring-stemm�d vessel\n[40]      O'er the ways of the waters; the wave-deeps were tossing,\n          Fought with the wind; winter in ice-bonds\n          Closed up the currents, till there came to the dwelling\n       10 A year in its course, as yet it revolveth,\n          If season propitious one alway regardeth,\n          World-cheering weathers. Then winter was gone,\n          Earth's bosom was lovely; the exile would get him,\n\n{He devises schemes of vengeance.}\n\n          The guest from the palace; on grewsomest vengeance\n       15 He brooded more eager than on oversea journeys,\n          Whe'r onset-of-anger he were able to 'complish,\n          The bairns of the Jutemen therein to remember.\n          Nowise refused he the duties of liegeman\n          When Hun of the Frisians the battle-sword L�fing,\n       20 Fairest of falchions, friendly did give him:\n          Its edges were famous in folk-talk of Jutland.\n          And savage sword-fury seized in its clutches\n          Bold-mooded Finn where he bode in his palace,\n\n{Guthlaf and Oslaf revenge Hn�f's slaughter.}\n\n          When the grewsome grapple Guthlaf and Oslaf\n       25 Had mournfully mentioned, the mere-journey over,\n          For sorrows half-blamed him; the flickering spirit\n          Could not bide in his bosom. Then the building was covered[2]\n\n{Finn is slain.}\n\n          With corpses of foemen, and Finn too was slaughtered,\n          The king with his comrades, and the queen made a prisoner.\n\n{The jewels of Finn, and his queen are carried away by the Danes.}\n\n       30 The troops of the Scyldings bore to their vessels\n          All that the land-king had in his palace,\n          Such trinkets and treasures they took as, on searching,\n          At Finn's they could find. They ferried to Daneland\n          The excellent woman on oversea journey,\n\n{The lay is concluded, and the main story is resumed.}\n\n       35 Led her to their land-folk.\" The lay was concluded,\n          The gleeman's recital. Shouts again rose then,\n          Bench-glee resounded, bearers then offered\n\n{Skinkers carry round the beaker.}\n\n          Wine from wonder-vats. Wealhtheo advanced then\n          Going 'neath gold-crown, where the good ones were seated\n\n[41]\n\n{Queen Wealhtheow greets Hrothgar, as he sits beside Hrothulf, his\nnephew.}\n\n       40 Uncle and nephew; their peace was yet mutual,\n          True each to the other. And Unferth the spokesman\n          Sat at the feet of the lord of the Scyldings:\n          Each trusted his spirit that his mood was courageous,\n          Though at fight he had failed in faith to his kinsmen.\n       45 Said the queen of the Scyldings: \"My lord and protector,\n          Treasure-bestower, take thou this beaker;\n          Joyance attend thee, gold-friend of heroes,\n\n{Be generous to the Geats.}\n\n          And greet thou the Geatmen with gracious responses!\n          So ought one to do. Be kind to the Geatmen,\n       50 In gifts not niggardly; anear and afar now\n          Peace thou enjoyest. Report hath informed me\n          Thou'lt have for a bairn the battle-brave hero.\n          Now is Heorot cleans�d, ring-palace gleaming;\n\n{Have as much joy as possible in thy hall, once more purified.}\n\n          Give while thou mayest many rewards,\n       55 And bequeath to thy kinsmen kingdom and people,\n          On wending thy way to the Wielder's splendor.\n          I know good Hrothulf, that the noble young troopers\n\n{I know that Hrothulf will prove faithful if he survive thee.}\n\n          He'll care for and honor, lord of the Scyldings,\n          If earth-joys thou endest earlier than he doth;\n       60 I reckon that recompense he'll render with kindness\n          Our offspring and issue, if that all he remember,\n          What favors of yore, when he yet was an infant,\n          We awarded to him for his worship and pleasure.\"\n          Then she turned by the bench where her sons were carousing,\n       65 Hrethric and Hrothmund, and the heroes' offspring,\n\n{Beowulf is sitting by the two royal sons.}\n\n          The war-youth together; there the good one was sitting\n          'Twixt the brothers twain, Beowulf Geatman.\n\n    [1] For 1130 (1) R. and Gr. suggest 'elne unflitme' as 1098 (1) reads.\n    The latter verse is undisputed; and, for the former, 'elne' would be\n    as possible as 'ealles,' and 'unflitme' is well supported. Accepting\n    'elne unflitme' for both, I would suggest '_very peaceably_' for both\n    places: (1) _Finn to Hengest very peaceably vowed with oaths_, etc.\n    (2) _Hengest then still the slaughter-stained winter remained there\n    with Finn very peaceably_. The two passages become thus correlatives,\n    the second a sequel of the first. 'Elne,' in the sense of very\n    (sw��e), needs no argument; and 'unflitme' (from 'fl�tan') can, it\n    seems to me, be more plausibly rendered 'peaceful,' 'peaceable,' than\n    'contestable,' or 'conquerable.'\n\n    [2] Some scholars have proposed 'roden'; the line would then read:\n    _Then the building was reddened, etc._, instead of 'covered.' The 'h'\n    may have been carried over from the three alliterating 'h's.'\n\n\n\n\nXIX.\n\nBEOWULF RECEIVES FURTHER HONOR.\n\n\n{More gifts are offered Beowulf.}\n\n          A beaker was borne him, and bidding to quaff it\n          Graciously given, and gold that was twisted\n          Pleasantly proffered, a pair of arm-jewels,\n[42]      Rings and corslet, of collars the greatest\n        5 I've heard of 'neath heaven. Of heroes not any\n          More splendid from jewels have I heard 'neath the welkin,\n\n{A famous necklace is referred to, in comparison with the gems presented\nto Beowulf.}\n\n          Since Hama off bore the Brosingmen's necklace,\n          The bracteates and jewels, from the bright-shining city,[1]\n          Eormenric's cunning craftiness fled from,\n       10 Chose gain everlasting. Geatish Higelac,\n          Grandson of Swerting, last had this jewel\n          When tramping 'neath banner the treasure he guarded,\n          The field-spoil defended; Fate offcarried him\n          When for deeds of daring he endured tribulation,\n       15 Hate from the Frisians; the ornaments bare he\n          O'er the cup of the currents, costly gem-treasures,\n          Mighty folk-leader, he fell 'neath his target;\n          The[2] corpse of the king then came into charge of\n          The race of the Frankmen, the mail-shirt and collar:\n       20 Warmen less noble plundered the fallen,\n          When the fight was finished; the folk of the Geatmen\n          The field of the dead held in possession.\n          The choicest of mead-halls with cheering resounded.\n          Wealhtheo discoursed, the war-troop addressed she:\n\n{Queen Wealhtheow magnifies Beowulf's achievements.}\n\n       25 \"This collar enjoy thou, Beowulf worthy,\n          Young man, in safety, and use thou this armor,\n          Gems of the people, and prosper thou fully,\n          Show thyself sturdy and be to these liegemen\n          Mild with instruction! I'll mind thy requital.\n       30 Thou hast brought it to pass that far and near\n          Forever and ever earthmen shall honor thee,\n          Even so widely as ocean surroundeth\n          The blustering bluffs. Be, while thou livest,\n[43]      A wealth-bless�d atheling. I wish thee most truly\n\n{May gifts never fail thee.}\n\n       35 Jewels and treasure. Be kind to my son, thou\n          Living in joyance! Here each of the nobles\n          Is true unto other, gentle in spirit,\n          Loyal to leader. The liegemen are peaceful,\n          The war-troops ready: well-drunken heroes,[3]\n       40 Do as I bid ye.\" Then she went to the settle.\n          There was choicest of banquets, wine drank the heroes:\n\n{They little know of the sorrow in store for them.}\n\n          Weird they knew not, destiny cruel,\n          As to many an earlman early it happened,\n          When evening had come and Hrothgar had parted\n       45 Off to his manor, the mighty to slumber.\n          Warriors unnumbered warded the building\n          As erst they did often: the ale-settle bared they,\n          'Twas covered all over with beds and pillows.\n\n{A doomed thane is there with them.}\n\n          Doomed unto death, down to his slumber\n       50 Bowed then a beer-thane. Their battle-shields placed they,\n          Bright-shining targets, up by their heads then;\n          O'er the atheling on ale-bench 'twas easy to see there\n          Battle-high helmet, burnie of ring-mail,\n\n{They were always ready for battle.}\n\n          And mighty war-spear. 'Twas the wont of that people\n       55 To constantly keep them equipped for the battle,[4]\n          At home or marching--in either condition--\n          At seasons just such as necessity ordered\n          As best for their ruler; that people was worthy.\n\n    [1] C. suggests a semicolon after 'city,' with 'he' as supplied\n    subject of 'fled' and 'chose.'\n\n    [2] For 'feorh' S. suggests 'feoh': 'corpse' in the translation would\n    then be changed to '_possessions_,' '_belongings_.' This is a better\n    reading than one joining, in such intimate syntactical relations,\n    things so unlike as 'corpse' and 'jewels.'\n\n    [3] S. suggests '_wine-joyous heroes_,' '_warriors elated with wine_.'\n\n    [4] I believe this translation brings out the meaning of the poet,\n    without departing seriously from the H.-So. text. 'Oft' frequently\n    means 'constantly,' 'continually,' not always 'often.'--Why 'an (on)\n    w�g gearwe' should be written '�nw�g-gearwe' (= ready for single\n    combat), I cannot see. 'Gearwe' occurs quite frequently with 'on'; cf.\n    B. 1110 (_ready for the pyre_), El. 222 (_ready for the glad\n    journey_). Moreover, what has the idea of single combat to do with B.\n    1247 ff.? The poet is giving an inventory of the arms and armor which\n    they lay aside on retiring, and he closes his narration by saying that\n    they were _always prepared for battle both at home and on the march_.\n\n[44]\n\n\n\n\nXX.\n\nTHE MOTHER OF GRENDEL.\n\n\n          They sank then to slumber. With sorrow one paid for\n          His evening repose, as often betid them\n          While Grendel was holding[1] the gold-bedecked palace,\n          Ill-deeds performing, till his end overtook him,\n        5 Death for his sins. 'Twas seen very clearly,\n\n{Grendel's mother is known to be thirsting for revenge.}\n\n          Known unto earth-folk, that still an avenger\n          Outlived the loathed one, long since the sorrow\n          Caused by the struggle; the mother of Grendel,\n          Devil-shaped woman, her woe ever minded,\n       10 Who was held to inhabit the horrible waters,\n\n{[Grendel's progenitor, Cain, is again referred to.]}\n\n          The cold-flowing currents, after Cain had become a\n          Slayer-with-edges to his one only brother,\n          The son of his sire; he set out then banished,\n          Marked as a murderer, man-joys avoiding,\n       15 Lived in the desert. Thence demons unnumbered\n\n{The poet again magnifies Beowulf's valor.}\n\n          Fate-sent awoke; one of them Grendel,\n          Sword-curs�d, hateful, who at Heorot met with\n          A man that was watching, waiting the struggle,\n          Where a horrid one held him with hand-grapple sturdy;\n       20 Nathless he minded the might of his body,\n          The glorious gift God had allowed him,\n          And folk-ruling Father's favor relied on,\n          His help and His comfort: so he conquered the foeman,\n          The hell-spirit humbled: he unhappy departed then,\n       25 Reaved of his joyance, journeying to death-haunts,\n          Foeman of man. His mother moreover\n\n{Grendel's mother comes to avenge her son.}\n\n          Eager and gloomy was anxious to go on\n          Her mournful mission, mindful of vengeance\n          For the death of her son. She came then to Heorot\n[45]   30 Where the Armor-Dane earlmen all through the building\n          Were lying in slumber. Soon there became then\n          Return[2] to the nobles, when the mother of Grendel\n          Entered the folk-hall; the fear was less grievous\n          By even so much as the vigor of maidens,\n       35 War-strength of women, by warrior is reckoned,\n          When well-carved weapon, worked with the hammer,\n          Blade very bloody, brave with its edges,\n          Strikes down the boar-sign that stands on the helmet.\n          Then the hard-edg�d weapon was heaved in the building,[3]\n       40 The brand o'er the benches, broad-lindens many\n          Hand-fast were lifted; for helmet he recked not,\n          For armor-net broad, whom terror laid hold of.\n          She went then hastily, outward would get her\n          Her life for to save, when some one did spy her;\n\n{She seizes a favorite liegemen of Hrothgar's.}\n\n       45 Soon she had grappled one of the athelings\n          Fast and firmly, when fenward she hied her;\n          That one to Hrothgar was liefest of heroes\n          In rank of retainer where waters encircle,\n          A mighty shield-warrior, whom she murdered at slumber,\n       50 A broadly-famed battle-knight. Beowulf was absent,\n\n{Beowulf was asleep in another part of the palace.}\n\n          But another apartment was erstwhile devoted\n          To the glory-decked Geatman when gold was distributed.\n          There was hubbub in Heorot. The hand that was famous\n          She grasped in its gore;[4] grief was renewed then\n[46]   55 In homes and houses: 'twas no happy arrangement\n          In both of the quarters to barter and purchase\n          With lives of their friends. Then the well-ag�d ruler,\n          The gray-headed war-thane, was woful in spirit,\n          When his long-trusted liegeman lifeless he knew of,\n\n{Beowulf is sent for.}\n\n       60 His dearest one gone. Quick from a room was\n          Beowulf brought, brave and triumphant.\n          As day was dawning in the dusk of the morning,\n\n{He comes at Hrothgar's summons.}\n\n          Went then that earlman, champion noble,\n          Came with comrades, where the clever one bided\n       65 Whether God all gracious would grant him a respite\n          After the woe he had suffered. The war-worthy hero\n          With a troop of retainers trod then the pavement\n          (The hall-building groaned), till he greeted the wise one,\n\n{Beowulf inquires how Hrothgar had enjoyed his night's rest.}\n\n          The earl of the Ingwins;[5] asked if the night had\n       70 Fully refreshed him, as fain he would have it.\n\n    [1] Several eminent authorities either read or emend the MS. so as to\n    make this verse read, _While Grendel was wasting the gold-bedecked\n    palace_. So 20_15 below: _ravaged the desert_.\n\n    [2] For 's�na' (1281), t.B. suggests 's�ra,' limiting 'edhwyrft.' Read\n    then: _Return of sorrows to the nobles, etc_. This emendation supplies\n    the syntactical gap after 'edhwyrft.'\n\n    [3] Some authorities follow Grein's lexicon in treating 'heard ecg' as\n    an adj. limiting 'sweord': H.-So. renders it as a subst. (So v. 1491.)\n    The sense of the translation would be the same.\n\n    [4] B. suggests 'under hr�f genam' (v. 1303). This emendation, as well\n    as an emendation with (?) to v. 739, he offers, because 'under'\n    baffles him in both passages. All we need is to take 'under' in its\n    secondary meaning of 'in,' which, though not given by Grein, occurs in\n    the literature. Cf. Chron. 876 (March's A.-S. Gram. � 355) and Oro.\n    Amaz. I. 10, where 'under' = _in the midst of_. Cf. modern Eng. 'in\n    such circumstances,' which interchanges in good usage with 'under such\n    circumstances.'\n\n    [5] For 'n�od-la�u' (1321) C. suggests 'n�ad-l��um,' and translates:\n    _asked whether the night had been pleasant to him after\n    crushing-hostility_.\n\n\n\n\nXXI.\n\nHROTHGAR'S ACCOUNT OF THE MONSTERS.\n\n\n{Hrothgar laments the death of �schere, his shoulder-companion.}\n\n          Hrothgar rejoined, helm of the Scyldings:\n          \"Ask not of joyance! Grief is renewed to\n          The folk of the Danemen. Dead is �schere,\n          Yrmenlaf's brother, older than he,\n        5 My true-hearted counsellor, trusty adviser,\n          Shoulder-companion, when fighting in battle\n          Our heads we protected, when troopers were clashing,\n\n{He was my ideal hero.}\n\n          And heroes were dashing; such an earl should be ever,\n          An erst-worthy atheling, as �schere proved him.\n       10 The flickering death-spirit became in Heorot\n          His hand-to-hand murderer; I can not tell whither\n          The cruel one turned in the carcass exulting,\n\n[47]\n\n{This horrible creature came to avenge Grendel's death.}\n\n          By cramming discovered.[1] The quarrel she wreaked then,\n          That last night igone Grendel thou killedst\n       15 In grewsomest manner, with grim-holding clutches,\n          Since too long he had lessened my liege-troop and wasted\n          My folk-men so foully. He fell in the battle\n          With forfeit of life, and another has followed,\n          A mighty crime-worker, her kinsman avenging,\n       20 And henceforth hath 'stablished her hatred unyielding,[2]\n          As it well may appear to many a liegeman,\n          Who mourneth in spirit the treasure-bestower,\n          Her heavy heart-sorrow; the hand is now lifeless\n          Which[3] availed you in every wish that you cherished.\n\n{I have heard my vassals speak of these two uncanny monsters who lived in\nthe moors.}\n\n       25 Land-people heard I, liegemen, this saying,\n          Dwellers in halls, they had seen very often\n          A pair of such mighty march-striding creatures,\n          Far-dwelling spirits, holding the moorlands:\n          One of them wore, as well they might notice,\n       30 The image of woman, the other one wretched\n          In guise of a man wandered in exile,\n          Except he was huger than any of earthmen;\n          Earth-dwelling people entitled him Grendel\n          In days of yore: they know not their father,\n       35 Whe'r ill-going spirits any were borne him\n\n{The inhabit the most desolate and horrible places.}\n\n          Ever before. They guard the wolf-coverts,\n          Lands inaccessible, wind-beaten nesses,\n          Fearfullest fen-deeps, where a flood from the mountains\n          'Neath mists of the nesses netherward rattles,\n       40 The stream under earth: not far is it henceward\n          Measured by mile-lengths that the mere-water standeth,\n          Which forests hang over, with frost-whiting covered,[4]\n[48]      A firm-rooted forest, the floods overshadow.\n          There ever at night one an ill-meaning portent\n       45 A fire-flood may see; 'mong children of men\n          None liveth so wise that wot of the bottom;\n          Though harassed by hounds the heath-stepper seek for,\n\n{Even the hounded deer will not seek refuge in these uncanny regions.}\n\n          Fly to the forest, firm-antlered he-deer,\n          Spurred from afar, his spirit he yieldeth,\n       50 His life on the shore, ere in he will venture\n          To cover his head. Uncanny the place is:\n          Thence upward ascendeth the surging of waters,\n          Wan to the welkin, when the wind is stirring\n          The weathers unpleasing, till the air groweth gloomy,\n\n{To thee only can I look for assistance.}\n\n       55 And the heavens lower. Now is help to be gotten\n          From thee and thee only! The abode thou know'st not,\n          The dangerous place where thou'rt able to meet with\n          The sin-laden hero: seek if thou darest!\n          For the feud I will fully fee thee with money,\n       60 With old-time treasure, as erstwhile I did thee,\n          With well-twisted jewels, if away thou shalt get thee.\"\n\n    [1] For 'gefr�gnod' (1334), K. and t.B. suggest 'gef�gnod,' rendering\n    '_rejoicing in her fill_.' This gives a parallel to '�se wlanc'\n    (1333).\n\n    [2] The line 'And ... yielding,' B. renders: _And she has performed a\n    deed of blood-vengeance whose effect is far-reaching_.\n\n    [3] 'S� �e' (1345) is an instance of masc. rel. with fem. antecedent.\n    So v. 1888, where 's� �e' refers to 'yldo.'\n\n    [4] For 'hr�mge' in the H.-So. edition, Gr. and others read 'hr�nde'\n    (=hr�nende), and translate: _which rustling forests overhang_.\n\n\n\n\nXXII.\n\nBEOWULF SEEKS GRENDEL'S MOTHER.\n\n\n          Beowulf answered, Ecgtheow's son:\n\n{Beowulf exhorts the old king to arouse himself for action.}\n\n          \"Grieve not, O wise one! for each it is better,\n          His friend to avenge than with vehemence wail him;\n          Each of us must the end-day abide of\n        5 His earthly existence; who is able accomplish\n          Glory ere death! To battle-thane noble\n          Lifeless lying, 'tis at last most fitting.\n          Arise, O king, quick let us hasten\n          To look at the footprint of the kinsman of Grendel!\n       10 I promise thee this now: to his place he'll escape not,\n          To embrace of the earth, nor to mountainous forest,\n          Nor to depths of the ocean, wherever he wanders.\n[49]      Practice thou now patient endurance\n          Of each of thy sorrows, as I hope for thee soothly!\"\n\n{Hrothgar rouses himself. His horse is brought.}\n\n       15 Then up sprang the old one, the All-Wielder thanked he,\n          Ruler Almighty, that the man had outspoken.\n          Then for Hrothgar a war-horse was decked with a bridle,\n          Curly-maned courser. The clever folk-leader\n\n{They start on the track of the female monster.}\n\n          Stately proceeded: stepped then an earl-troop\n       20 Of linden-wood bearers. Her footprints were seen then\n          Widely in wood-paths, her way o'er the bottoms,\n          Where she faraway fared o'er fen-country murky,\n          Bore away breathless the best of retainers\n          Who pondered with Hrothgar the welfare of country.\n       25 The son of the athelings then went o'er the stony,\n          Declivitous cliffs, the close-covered passes,\n          Narrow passages, paths unfrequented,\n          Nesses abrupt, nicker-haunts many;\n          One of a few of wise-mooded heroes,\n       30 He onward advanced to view the surroundings,\n          Till he found unawares woods of the mountain\n          O'er hoar-stones hanging, holt-wood unjoyful;\n          The water stood under, welling and gory.\n          'Twas irksome in spirit to all of the Danemen,\n       35 Friends of the Scyldings, to many a liegeman\n\n{The sight of �schere's head causes them great sorrow.}\n\n          Sad to be suffered, a sorrow unlittle\n          To each of the earlmen, when to �schere's head they\n          Came on the cliff. The current was seething\n          With blood and with gore (the troopers gazed on it).\n       40 The horn anon sang the battle-song ready.\n          The troop were all seated; they saw 'long the water then\n\n{The water is filled with serpents and sea-dragons.}\n\n          Many a serpent, mere-dragons wondrous\n          Trying the waters, nickers a-lying\n          On the cliffs of the nesses, which at noonday full often\n       45 Go on the sea-deeps their sorrowful journey,\n          Wild-beasts and wormkind; away then they hastened\n\n{One of them is killed by Beowulf.}\n\n          Hot-mooded, hateful, they heard the great clamor,\n          The war-trumpet winding. One did the Geat-prince\n[50]      Sunder from earth-joys, with arrow from bowstring,\n       50 From his sea-struggle tore him, that the trusty war-missile\n\n{The dead beast is a poor swimmer}\n\n          Pierced to his vitals; he proved in the currents\n          Less doughty at swimming whom death had offcarried.\n          Soon in the waters the wonderful swimmer\n          Was straitened most sorely with sword-pointed boar-spears,\n       55 Pressed in the battle and pulled to the cliff-edge;\n          The liegemen then looked on the loath-fashioned stranger.\n\n{Beowulf prepares for a struggle with the monster.}\n\n          Beowulf donned then his battle-equipments,\n          Cared little for life; inlaid and most ample,\n          The hand-woven corslet which could cover his body,\n       60 Must the wave-deeps explore, that war might be powerless\n          To harm the great hero, and the hating one's grasp might\n          Not peril his safety; his head was protected\n          By the light-flashing helmet that should mix with the bottoms,\n          Trying the eddies, treasure-emblazoned,\n       65 Encircled with jewels, as in seasons long past\n          The weapon-smith worked it, wondrously made it,\n          With swine-bodies fashioned it, that thenceforward no longer\n          Brand might bite it, and battle-sword hurt it.\n          And that was not least of helpers in prowess\n\n{He has Unferth's sword in his hand.}\n\n       70 That Hrothgar's spokesman had lent him when straitened;\n          And the hilted hand-sword was Hrunting entitled,\n          Old and most excellent 'mong all of the treasures;\n          Its blade was of iron, blotted with poison,\n          Hardened with gore; it failed not in battle\n       75 Any hero under heaven in hand who it brandished,\n          Who ventured to take the terrible journeys,\n          The battle-field sought; not the earliest occasion\n          That deeds of daring 'twas destined to 'complish.\n\n{Unferth has little use for swords.}\n\n          Ecglaf's kinsman minded not soothly,\n       80 Exulting in strength, what erst he had spoken\n          Drunken with wine, when the weapon he lent to\n          A sword-hero bolder; himself did not venture\n          'Neath the strife of the currents his life to endanger,\n[51]      To fame-deeds perform; there he forfeited glory,\n       85 Repute for his strength. Not so with the other\n          When he clad in his corslet had equipped him for battle.\n\n\n\n\nXXIII.\n\nBEOWULF'S FIGHT WITH GRENDEL'S MOTHER.\n\n\n{Beowulf makes a parting speech to Hrothgar.}\n\n          Beowulf spake, Ecgtheow's son:\n          \"Recall now, oh, famous kinsman of Healfdene,\n          Prince very prudent, now to part I am ready,\n          Gold-friend of earlmen, what erst we agreed on,\n\n{If I fail, act as a kind liegelord to my thanes,}\n\n        5 Should I lay down my life in lending thee assistance,\n          When my earth-joys were over, thou wouldst evermore serve me\n          In stead of a father; my faithful thanemen,\n          My trusty retainers, protect thou and care for,\n          Fall I in battle: and, Hrothgar belov�d,\n\n{and send Higelac the jewels thou hast given me}\n\n       10 Send unto Higelac the high-valued jewels\n          Thou to me hast allotted. The lord of the Geatmen\n          May perceive from the gold, the Hrethling may see it\n\n{I should like my king to know how generous a lord I found thee to be.}\n\n          When he looks on the jewels, that a gem-giver found I\n          Good over-measure, enjoyed him while able.\n       15 And the ancient heirloom Unferth permit thou,\n          The famed one to have, the heavy-sword splendid[1]\n          The hard-edg�d weapon; with Hrunting to aid me,\n          I shall gain me glory, or grim-death shall take me.\"\n\n{Beowulf is eager for the fray.}\n\n          The atheling of Geatmen uttered these words and\n       20 Heroic did hasten, not any rejoinder\n          Was willing to wait for; the wave-current swallowed\n\n{He is a whole day reaching the bottom of the sea.}\n\n          The doughty-in-battle. Then a day's-length elapsed ere\n          He was able to see the sea at its bottom.\n          Early she found then who fifty of winters\n       25 The course of the currents kept in her fury,\n          Grisly and greedy, that the grim one's dominion\n\n[52]\n\n{Grendel's mother knows that some one has reached her domains.}\n\n          Some one of men from above was exploring.\n          Forth did she grab them, grappled the warrior\n          With horrible clutches; yet no sooner she injured\n       30 His body unscath�d: the burnie out-guarded,\n          That she proved but powerless to pierce through the armor,\n          The limb-mail locked, with loath-grabbing fingers.\n          The sea-wolf bare then, when bottomward came she,\n\n{She grabs him, and bears him to her den.}\n\n          The ring-prince homeward, that he after was powerless\n       35 (He had daring to do it) to deal with his weapons,\n          But many a mere-beast tormented him swimming,\n\n{Sea-monsters bite and strike him.}\n\n          Flood-beasts no few with fierce-biting tusks did\n          Break through his burnie, the brave one pursued they.\n          The earl then discovered he was down in some cavern\n       40 Where no water whatever anywise harmed him,\n          And the clutch of the current could come not anear him,\n          Since the roofed-hall prevented; brightness a-gleaming\n          Fire-light he saw, flashing resplendent.\n          The good one saw then the sea-bottom's monster,\n\n{Beowulf attacks the mother of Grendel.}\n\n       45 The mighty mere-woman; he made a great onset\n          With weapon-of-battle, his hand not desisted\n          From striking, that war-blade struck on her head then\n          A battle-song greedy. The stranger perceived then\n\n{The sword will not bite.}\n\n          The sword would not bite, her life would not injure,\n       50 But the falchion failed the folk-prince when straitened:\n          Erst had it often onsets encountered,\n          Oft cloven the helmet, the fated one's armor:\n          'Twas the first time that ever the excellent jewel\n          Had failed of its fame. Firm-mooded after,\n       55 Not heedless of valor, but mindful of glory,\n          Was Higelac's kinsman; the hero-chief angry\n          Cast then his carved-sword covered with jewels\n          That it lay on the earth, hard and steel-pointed;\n\n{The hero throws down all weapons, and again trusts to his hand-grip.}\n\n          He hoped in his strength, his hand-grapple sturdy.\n       60 So any must act whenever he thinketh\n          To gain him in battle glory unending,\n          And is reckless of living. The lord of the War-Geats\n[53]      (He shrank not from battle) seized by the shoulder[2]\n          The mother of Grendel; then mighty in struggle\n       65 Swung he his enemy, since his anger was kindled,\n          That she fell to the floor. With furious grapple\n\n{Beowulf falls.}\n\n          She gave him requital[3] early thereafter,\n          And stretched out to grab him; the strongest of warriors\n          Faint-mooded stumbled, till he fell in his traces,\n\n{The monster sits on him with drawn sword.}\n\n       70 Foot-going champion. Then she sat on the hall-guest\n          And wielded her war-knife wide-bladed, flashing,\n          For her son would take vengeance, her one only bairn.\n\n{His armor saves his life.}\n\n          His breast-armor woven bode on his shoulder;\n          It guarded his life, the entrance defended\n       75 'Gainst sword-point and edges. Ecgtheow's son there\n          Had fatally journeyed, champion of Geatmen,\n          In the arms of the ocean, had the armor not given,\n          Close-woven corslet, comfort and succor,\n\n{God arranged for his escape.}\n\n          And had God most holy not awarded the victory,\n       80 All-knowing Lord; easily did heaven's\n          Ruler most righteous arrange it with justice;[4]\n          Uprose he erect ready for battle.\n\n    [1] Kl. emends 'w�l-sweord.' The half-line would then read, '_the\n    battle-sword splendid_.'--For 'heard-ecg' in next half-verse, see note\n    to 20_39 above.\n\n    [2] Sw., R., and t.B. suggest 'feaxe' for 'eaxle' (1538) and render:\n    _Seized by the hair_.\n\n    [3] If 'hand-l�an' be accepted (as the MS. has it), the line will\n    read: _She hand-reward gave him early thereafter_.\n\n    [4] Sw. and S. change H.-So.'s semicolon (v. 1557) to a comma, and\n    translate: _The Ruler of Heaven arranged it in justice easily, after\n    he arose again_.\n\n\n\n\nXXIV.\n\nBEOWULF IS DOUBLE-CONQUEROR.\n\n\n{Beowulf grasps a giant-sword,}\n\n          Then he saw mid the war-gems a weapon of victory,\n          An ancient giant-sword, of edges a-doughty,\n          Glory of warriors: of weapons 'twas choicest,\n          Only 'twas larger than any man else was\n[54]    5 Able to bear to the battle-encounter,\n          The good and splendid work of the giants.\n          He grasped then the sword-hilt, knight of the Scyldings,\n          Bold and battle-grim, brandished his ring-sword,\n          Hopeless of living, hotly he smote her,\n       10 That the fiend-woman's neck firmly it grappled,\n\n{and fells the female monster.}\n\n          Broke through her bone-joints, the bill fully pierced her\n          Fate-curs�d body, she fell to the ground then:\n          The hand-sword was bloody, the hero exulted.\n          The brand was brilliant, brightly it glimmered,\n       15 Just as from heaven gemlike shineth\n          The torch of the firmament. He glanced 'long the building,\n          And turned by the wall then, Higelac's vassal\n          Raging and wrathful raised his battle-sword\n          Strong by the handle. The edge was not useless\n       20 To the hero-in-battle, but he speedily wished to\n          Give Grendel requital for the many assaults he\n          Had worked on the West-Danes not once, but often,\n          When he slew in slumber the subjects of Hrothgar,\n          Swallowed down fifteen sleeping retainers\n       25 Of the folk of the Danemen, and fully as many\n          Carried away, a horrible prey.\n          He gave him requital, grim-raging champion,\n\n{Beowulf sees the body of Grendel, and cuts off his head.}\n\n          When he saw on his rest-place weary of conflict\n          Grendel lying, of life-joys bereav�d,\n       30 As the battle at Heorot erstwhile had scathed him;\n          His body far bounded, a blow when he suffered,\n          Death having seized him, sword-smiting heavy,\n          And he cut off his head then. Early this noticed\n          The clever carles who as comrades of Hrothgar\n\n{The waters are gory.}\n\n       35 Gazed on the sea-deeps, that the surging wave-currents\n          Were mightily mingled, the mere-flood was gory:\n          Of the good one the gray-haired together held converse,\n\n{Beowulf is given up for dead.}\n\n          The hoary of head, that they hoped not to see again\n          The atheling ever, that exulting in victory\n       40 He'd return there to visit the distinguished folk-ruler:\n[55]      Then many concluded the mere-wolf had killed him.[1]\n          The ninth hour came then. From the ness-edge departed\n          The bold-mooded Scyldings; the gold-friend of heroes\n          Homeward betook him. The strangers sat down then\n       45 Soul-sick, sorrowful, the sea-waves regarding:\n          They wished and yet weened not their well-loved friend-lord\n\n{The giant-sword melts.}\n\n          To see any more. The sword-blade began then,\n          The blood having touched it, contracting and shriveling\n          With battle-icicles; 'twas a wonderful marvel\n       50 That it melted entirely, likest to ice when\n          The Father unbindeth the bond of the frost and\n          Unwindeth the wave-bands, He who wieldeth dominion\n          Of times and of tides: a truth-firm Creator.\n          Nor took he of jewels more in the dwelling,\n       55 Lord of the Weders, though they lay all around him,\n          Than the head and the handle handsome with jewels;\n[56]      The brand early melted, burnt was the weapon:[2]\n          So hot was the blood, the strange-spirit poisonous\n\n{The hero swims back to the realms of day.}\n\n          That in it did perish. He early swam off then\n       60 Who had bided in combat the carnage of haters,\n          Went up through the ocean; the eddies were cleans�d,\n          The spacious expanses, when the spirit from farland\n          His life put aside and this short-lived existence.\n          The seamen's defender came swimming to land then\n       65 Doughty of spirit, rejoiced in his sea-gift,\n          The bulky burden which he bore in his keeping.\n          The excellent vassals advanced then to meet him,\n          To God they were grateful, were glad in their chieftain,\n          That to see him safe and sound was granted them.\n       70 From the high-minded hero, then, helmet and burnie\n          Were speedily loosened: the ocean was putrid,\n          The water 'neath welkin weltered with gore.\n          Forth did they fare, then, their footsteps retracing,\n          Merry and mirthful, measured the earth-way,\n       75 The highway familiar: men very daring[3]\n          Bare then the head from the sea-cliff, burdening\n          Each of the earlmen, excellent-valiant.\n\n{It takes four men to carry Grendel's head on a spear.}\n\n          Four of them had to carry with labor\n          The head of Grendel to the high towering gold-hall\n       80 Upstuck on the spear, till fourteen most-valiant\n          And battle-brave Geatmen came there going\n          Straight to the palace: the prince of the people\n          Measured the mead-ways, their mood-brave companion.\n          The atheling of earlmen entered the building,\n       85 Deed-valiant man, adorned with distinction,\n          Doughty shield-warrior, to address King Hrothgar:\n[57]      Then hung by the hair, the head of Grendel\n          Was borne to the building, where beer-thanes were drinking,\n          Loth before earlmen and eke 'fore the lady:\n       90 The warriors beheld then a wonderful sight.\n\n    [1] '��s monige gewear�' (1599) and 'hafa� ��s geworden' (2027).--In a\n    paper published some years ago in one of the Johns Hopkins University\n    circulars, I tried to throw upon these two long-doubtful passages some\n    light derived from a study of like passages in Alfred's prose.--The\n    impersonal verb 'geweor�an,' with an accus. of the person, and a\n    ��t-clause is used several times with the meaning 'agree.' See Orosius\n    (Sweet's ed.) 178_7; 204_34; 208_28; 210_15; 280_20. In the two\n    Beowulf passages, the ��t-clause is anticipated by '��s,' which is\n    clearly a gen. of the thing agreed on.\n\n    The first passage (v. 1599 (b)-1600) I translate literally: _Then many\n    agreed upon this (namely), that the sea-wolf had killed him_.\n\n    The second passage (v. 2025 (b)-2027): _She is promised ...; to this\n    the friend of the Scyldings has agreed, etc_. By emending 'is' instead\n    of 'w�s' (2025), the tenses will be brought into perfect harmony.\n\n    In v. 1997 ff. this same idiom occurs, and was noticed in B.'s great\n    article on Beowulf, which appeared about the time I published my\n    reading of 1599 and 2027. Translate 1997 then: _Wouldst let the\n    South-Danes themselves decide about their struggle with Grendel_. Here\n    'S��-Dene' is accus. of person, and 'g��e' is gen. of thing agreed on.\n\n    With such collateral support as that afforded by B. (P. and B. XII.\n    97), I have no hesitation in departing from H.-So., my usual guide.\n\n    The idiom above treated runs through A.-S., Old Saxon, and other\n    Teutonic languages, and should be noticed in the lexicons.\n\n    [2] 'Br�den-m�l' is regarded by most scholars as meaning a damaskeened\n    sword. Translate: _The damaskeened sword burned up_. Cf. 25_16 and\n    note.\n\n    [3] 'Cyning-balde' (1635) is the much-disputed reading of K. and Th.\n    To render this, \"_nobly bold_,\" \"_excellently bold_,\" have been\n    suggested. B. would read 'cyning-holde' (cf. 290), and render: _Men\n    well-disposed towards the king carried the head, etc._ 'Cynebealde,'\n    says t.B., endorsing Gr.\n\n\n\n\nXXV.\n\nBEOWULF BRINGS HIS TROPHIES.--HROTHGAR'S GRATITUDE.\n\n\n{Beowulf relates his last exploit.}\n\n          Beowulf spake, offspring of Ecgtheow:\n          \"Lo! we blithely have brought thee, bairn of Healfdene,\n          Prince of the Scyldings, these presents from ocean\n          Which thine eye looketh on, for an emblem of glory.\n        5 I came off alive from this, narrowly 'scaping:\n          In war 'neath the water the work with great pains I\n          Performed, and the fight had been finished quite nearly,\n          Had God not defended me. I failed in the battle\n          Aught to accomplish, aided by Hrunting,\n       10 Though that weapon was worthy, but the Wielder of earth-folk\n\n{God was fighting with me.}\n\n          Gave me willingly to see on the wall a\n          Heavy old hand-sword hanging in splendor\n          (He guided most often the lorn and the friendless),\n          That I swung as a weapon. The wards of the house then\n       15 I killed in the conflict (when occasion was given me).\n          Then the battle-sword burned, the brand that was lifted,[1]\n          As the blood-current sprang, hottest of war-sweats;\n          Seizing the hilt, from my foes I offbore it;\n          I avenged as I ought to their acts of malignity,\n       20 The murder of Danemen. I then make thee this promise,\n\n{Heorot is freed from monsters.}\n\n          Thou'lt be able in Heorot careless to slumber\n          With thy throng of heroes and the thanes of thy people\n          Every and each, of greater and lesser,\n          And thou needest not fear for them from the selfsame direction\n       25 As thou formerly fearedst, oh, folk-lord of Scyldings,\n[58]     End-day for earlmen.\" To the age-hoary man then,\n\n{The famous sword is presented to Hrothgar.}\n\n          The gray-haired chieftain, the gold-fashioned sword-hilt,\n          Old-work of giants, was thereupon given;\n          Since the fall of the fiends, it fell to the keeping\n       30 Of the wielder of Danemen, the wonder-smith's labor,\n          And the bad-mooded being abandoned this world then,\n          Opponent of God, victim of murder,\n          And also his mother; it went to the keeping\n          Of the best of the world-kings, where waters encircle,\n       35 Who the scot divided in Scylding dominion.\n\n{Hrothgar looks closely at the old sword.}\n\n          Hrothgar discoursed, the hilt he regarded,\n          The ancient heirloom where an old-time contention's\n          Beginning was graven: the gurgling currents,\n          The flood slew thereafter the race of the giants,\n       40 They had proved themselves daring: that people was loth to\n\n{It had belonged to a race hateful to God.}\n\n          The Lord everlasting, through lash of the billows\n          The Father gave them final requital.\n          So in letters of rune on the clasp of the handle\n          Gleaming and golden, 'twas graven exactly,\n       45 Set forth and said, whom that sword had been made for,\n          Finest of irons, who first it was wrought for,\n          Wreathed at its handle and gleaming with serpents.\n          The wise one then said (silent they all were)\n\n{Hrothgar praises Beowulf.}\n\n          Son of old Healfdene: \"He may say unrefuted\n       50 Who performs 'mid the folk-men fairness and truth\n          (The hoary old ruler remembers the past),\n          That better by birth is this bairn of the nobles!\n          Thy fame is extended through far-away countries,\n          Good friend Beowulf, o'er all of the races,\n       55 Thou holdest all firmly, hero-like strength with\n          Prudence of spirit. I'll prove myself grateful\n          As before we agreed on; thou granted for long shalt\n          Become a great comfort to kinsmen and comrades,\n\n{Heremod's career is again contrasted with Beowulf's.}\n\n          A help unto heroes. Heremod became not\n       60 Such to the Scyldings, successors of Ecgwela;\n          He grew not to please them, but grievous destruction,\n[59]      And diresome death-woes to Danemen attracted;\n          He slew in anger his table-companions,\n          Trustworthy counsellors, till he turned off lonely\n       65 From world-joys away, wide-famous ruler:\n          Though high-ruling heaven in hero-strength raised him,\n          In might exalted him, o'er men of all nations\n          Made him supreme, yet a murderous spirit\n          Grew in his bosom: he gave then no ring-gems\n\n{A wretched failure of a king, to give no jewels to his retainers.}\n\n       70 To the Danes after custom; endured he unjoyful\n          Standing the straits from strife that was raging,\n          Longsome folk-sorrow. Learn then from this,\n          Lay hold of virtue! Though laden with winters,\n          I have sung thee these measures. 'Tis a marvel to tell it,\n\n{Hrothgar moralizes.}\n\n       75 How all-ruling God from greatness of spirit\n          Giveth wisdom to children of men,\n          Manor and earlship: all things He ruleth.\n          He often permitteth the mood-thought of man of\n          The illustrious lineage to lean to possessions,\n       80 Allows him earthly delights at his manor,\n          A high-burg of heroes to hold in his keeping,\n          Maketh portions of earth-folk hear him,\n          And a wide-reaching kingdom so that, wisdom failing him,\n          He himself is unable to reckon its boundaries;\n       85 He liveth in luxury, little debars him,\n          Nor sickness nor age, no treachery-sorrow\n          Becloudeth his spirit, conflict nowhere,\n          No sword-hate, appeareth, but all of the world doth\n          Wend as he wisheth; the worse he knoweth not,\n       90 Till arrant arrogance inward pervading,\n          Waxeth and springeth, when the warder is sleeping,\n          The guard of the soul: with sorrows encompassed,\n          Too sound is his slumber, the slayer is near him,\n          Who with bow and arrow aimeth in malice.\n\n[60]\n\n    [1] Or rather, perhaps, '_the inlaid, or damaskeened weapon_.' Cf.\n    24_57 and note.\n\n\n\n\nXXVI.\n\nHROTHGAR MORALIZES.--REST AFTER LABOR.\n\n\n{A wounded spirit.}\n\n          \"Then bruised in his bosom he with bitter-toothed missile\n          Is hurt 'neath his helmet: from harmful pollution\n          He is powerless to shield him by the wonderful mandates\n          Of the loath-curs�d spirit; what too long he hath holden\n        5 Him seemeth too small, savage he hoardeth,\n          Nor boastfully giveth gold-plated rings,[1]\n          The fate of the future flouts and forgetteth\n          Since God had erst given him greatness no little,\n          Wielder of Glory. His end-day anear,\n       10 It afterward happens that the bodily-dwelling\n          Fleetingly fadeth, falls into ruins;\n          Another lays hold who doleth the ornaments,\n          The nobleman's jewels, nothing lamenting,\n          Heedeth no terror. Oh, Beowulf dear,\n       15 Best of the heroes, from bale-strife defend thee,\n          And choose thee the better, counsels eternal;\n\n{Be not over proud: life is fleeting, and its strength soon wasteth away.}\n\n          Beware of arrogance, world-famous champion!\n          But a little-while lasts thy life-vigor's fulness;\n          'Twill after hap early, that illness or sword-edge\n       20 Shall part thee from strength, or the grasp of the fire,\n          Or the wave of the current, or clutch of the edges,\n          Or flight of the war-spear, or age with its horrors,\n          Or thine eyes' bright flashing shall fade into darkness:\n          'Twill happen full early, excellent hero,\n\n{Hrothgar gives an account of his reign.}\n\n       25 That death shall subdue thee. So the Danes a half-century\n          I held under heaven, helped them in struggles\n          'Gainst many a race in middle-earth's regions,\n          With ash-wood and edges, that enemies none\n          On earth molested me. Lo! offsetting change, now,\n\n[61]\n\n{Sorrow after joy.}\n\n       30 Came to my manor, grief after joyance,\n          When Grendel became my constant visitor,\n          Inveterate hater: I from that malice\n          Continually travailed with trouble no little.\n          Thanks be to God that I gained in my lifetime,\n       35 To the Lord everlasting, to look on the gory\n          Head with mine eyes, after long-lasting sorrow!\n          Go to the bench now, battle-adorn�d\n          Joy in the feasting: of jewels in common\n          We'll meet with many when morning appeareth.\"\n       40 The Geatman was gladsome, ganged he immediately\n          To go to the bench, as the clever one bade him.\n          Then again as before were the famous-for-prowess,\n          Hall-inhabiters, handsomely banqueted,\n          Feasted anew. The night-veil fell then\n       45 Dark o'er the warriors. The courtiers rose then;\n          The gray-haired was anxious to go to his slumbers,\n          The hoary old Scylding. Hankered the Geatman,\n\n{Beowulf is fagged, and seeks rest.}\n\n          The champion doughty, greatly, to rest him:\n          An earlman early outward did lead him,\n       50 Fagged from his faring, from far-country springing,\n          Who for etiquette's sake all of a liegeman's\n          Needs regarded, such as seamen at that time\n          Were bounden to feel. The big-hearted rested;\n          The building uptowered, spacious and gilded,\n       55 The guest within slumbered, till the sable-clad raven\n          Blithely foreboded the beacon of heaven.\n          Then the bright-shining sun o'er the bottoms came going;[2]\n          The warriors hastened, the heads of the peoples\n          Were ready to go again to their peoples,\n\n{The Geats prepare to leave Dane-land.}\n\n       60 The high-mooded farer would faraway thenceward\n          Look for his vessel. The valiant one bade then,[3]\n\n[62]\n\n{Unferth asks Beowulf to accept his sword as a gift. Beowulf thanks him.}\n\n          Offspring of Ecglaf, off to bear Hrunting,\n          To take his weapon, his well-beloved iron;\n          He him thanked for the gift, saying good he accounted\n       65 The war-friend and mighty, nor chid he with words then\n          The blade of the brand: 'twas a brave-mooded hero.\n          When the warriors were ready, arrayed in their trappings,\n          The atheling dear to the Danemen advanced then\n          On to the dais, where the other was sitting,\n       70 Grim-mooded hero, greeted King Hrothgar.\n\n    [1] K. says '_proudly giveth_.'--Gr. says, '_And gives no gold-plated\n    rings, in order to incite the recipient to boastfulness_.'--B.\n    suggests 'gyld' for 'gylp,' and renders: _And gives no beaten rings\n    for reward_.\n\n    [2] If S.'s emendation be accepted, v. 57 will read: _Then came the\n    light, going bright after darkness: the warriors, etc_.\n\n    [3] As the passage stands in H.-So., Unferth presents Beowulf with the\n    sword Hrunting, and B. thanks him for the gift. If, however, the\n    suggestions of Grdtvg. and M. be accepted, the passage will read:\n    _Then the brave one (_i.e._ Beowulf) commanded that Hrunting be borne\n    to the son of Ecglaf (Unferth), bade him take his sword, his dear\n    weapon; he (B.) thanked him (U.) for the loan, etc_.\n\n\n\n\nXXVII.\n\nSORROW AT PARTING.\n\n\n{Beowulf's farewell.}\n\n          Beowulf spake, Ecgtheow's offspring:\n          \"We men of the water wish to declare now\n          Fared from far-lands, we're firmly determined\n          To seek King Higelac. Here have we fitly\n        5 Been welcomed and feasted, as heart would desire it;\n          Good was the greeting. If greater affection\n          I am anywise able ever on earth to\n          Gain at thy hands, ruler of heroes,\n          Than yet I have done, I shall quickly be ready\n\n{I shall be ever ready to aid thee.}\n\n       10 For combat and conflict. O'er the course of the waters\n          Learn I that neighbors alarm thee with terror,\n          As haters did whilom, I hither will bring thee\n          For help unto heroes henchmen by thousands.\n\n{My liegelord will encourage me in aiding thee.}\n\n          I know as to Higelac, the lord of the Geatmen,\n       15 Though young in years, he yet will permit me,\n          By words and by works, ward of the people,\n          Fully to furnish thee forces and bear thee\n          My lance to relieve thee, if liegemen shall fail thee,\n          And help of my hand-strength; if Hrethric be treating,\n[63]   20 Bairn of the king, at the court of the Geatmen,\n          He thereat may find him friends in abundance:\n          Faraway countries he were better to seek for\n          Who trusts in himself.\" Hrothgar discoursed then,\n          Making rejoinder: \"These words thou hast uttered\n       25 All-knowing God hath given thy spirit!\n\n{O Beowulf, thou art wise beyond thy years.}\n\n          Ne'er heard I an earlman thus early in life\n          More clever in speaking: thou'rt cautious of spirit,\n          Mighty of muscle, in mouth-answers prudent.\n          I count on the hope that, happen it ever\n       30 That missile shall rob thee of Hrethel's descendant,\n          Edge-horrid battle, and illness or weapon\n          Deprive thee of prince, of people's protector,\n\n{Should Higelac die, the Geats could find no better successor than thou\nwouldst make.}\n\n          And life thou yet holdest, the Sea-Geats will never\n          Find a more fitting folk-lord to choose them,\n       35 Gem-ward of heroes, than _thou_ mightest prove thee,\n          If the kingdom of kinsmen thou carest to govern.\n          Thy mood-spirit likes me the longer the better,\n          Beowulf dear: thou hast brought it to pass that\n          To both these peoples peace shall be common,\n\n{Thou hast healed the ancient breach between our races.}\n\n       40 To Geat-folk and Danemen, the strife be suspended,\n          The secret assailings they suffered in yore-days;\n          And also that jewels be shared while I govern\n          The wide-stretching kingdom, and that many shall visit\n          Others o'er the ocean with excellent gift-gems:\n       45 The ring-adorned bark shall bring o'er the currents\n          Presents and love-gifts. This people I know\n          Tow'rd foeman and friend firmly established,[1]\n          After ancient etiquette everywise blameless.\"\n          Then the warden of earlmen gave him still farther,\n\n{Parting gifts}\n\n       50 Kinsman of Healfdene, a dozen of jewels,\n          Bade him safely seek with the presents\n          His well-beloved people, early returning.\n\n[64]\n\n{Hrothgar kisses Beowulf, and weeps.}\n\n          Then the noble-born king kissed the distinguished,\n          Dear-lov�d liegeman, the Dane-prince saluted him,\n       55 And clasp�d his neck; tears from him fell,\n          From the gray-headed man: he two things expected,\n          Ag�d and reverend, but rather the second,\n          [2]That bold in council they'd meet thereafter.\n          The man was so dear that he failed to suppress the\n       60 Emotions that moved him, but in mood-fetters fastened\n\n{The old king is deeply grieved to part with his benefactor.}\n\n          The long-famous hero longeth in secret\n          Deep in his spirit for the dear-beloved man\n          Though not a blood-kinsman. Beowulf thenceward,\n          Gold-splendid warrior, walked o'er the meadows\n       65 Exulting in treasure: the sea-going vessel\n          Riding at anchor awaited its owner.\n          As they pressed on their way then, the present of Hrothgar\n\n{Giving liberally is the true proof of kingship.}\n\n          Was frequently referred to: a folk-king indeed that\n          Everyway blameless, till age did debar him\n       70 The joys of his might, which hath many oft injured.\n\n    [1] For 'geworhte,' the crux of this passage, B. proposes 'ge��hte,'\n    rendering: _I know this people with firm thought every way blameless\n    towards foe and friends_.\n\n    [2] S. and B. emend so as to negative the verb 'meet.' \"Why should\n    Hrothgar weep if he expects to meet Beowulf again?\" both these\n    scholars ask. But the weeping is mentioned before the 'expectations':\n    the tears may have been due to many emotions, especially gratitude,\n    struggling for expression.\n\n\n\n\nXXVIII.\n\nTHE HOMEWARD JOURNEY.--THE TWO QUEENS.\n\n\n          Then the band of very valiant retainers\n          Came to the current; they were clad all in armor,\n\n{The coast-guard again.}\n\n          In link-woven burnies. The land-warder noticed\n          The return of the earlmen, as he erstwhile had seen them;\n        5 Nowise with insult he greeted the strangers\n          From the naze of the cliff, but rode on to meet them;\n          Said the bright-armored visitors[1] vesselward traveled\n[65]      Welcome to Weders. The wide-bosomed craft then\n          Lay on the sand, laden with armor,\n       10 With horses and jewels, the ring-stemm�d sailer:\n          The mast uptowered o'er the treasure of Hrothgar.\n\n{Beowulf gives the guard a handsome sword.}\n\n          To the boat-ward a gold-bound brand he presented,\n          That he was afterwards honored on the ale-bench more highly\n          As the heirloom's owner. [2]Set he out on his vessel,\n       15 To drive on the deep, Dane-country left he.\n          Along by the mast then a sea-garment fluttered,\n          A rope-fastened sail. The sea-boat resounded,\n          The wind o'er the waters the wave-floater nowise\n          Kept from its journey; the sea-goer traveled,\n       20 The foamy-necked floated forth o'er the currents,\n          The well-fashioned vessel o'er the ways of the ocean,\n\n{The Geats see their own land again.}\n\n          Till they came within sight of the cliffs of the Geatmen,\n          The well-known headlands. The wave-goer hastened\n          Driven by breezes, stood on the shore.\n\n{The port-warden is anxiously looking for them.}\n\n       25 Prompt at the ocean, the port-ward was ready,\n          Who long in the past outlooked in the distance,[3]\n          At water's-edge waiting well-lov�d heroes;\n          He bound to the bank then the broad-bosomed vessel\n          Fast in its fetters, lest the force of the waters\n       30 Should be able to injure the ocean-wood winsome.\n          Bade he up then take the treasure of princes,\n          Plate-gold and fretwork; not far was it thence\n          To go off in search of the giver of jewels:\n[66]      Hrethel's son Higelac at home there remaineth,[4]\n       35 Himself with his comrades close to the sea-coast.\n          The building was splendid, the king heroic,\n          Great in his hall, Hygd very young was,\n\n{Hygd, the noble queen of Higelac, lavish of gifts.}\n\n          Fine-mooded, clever, though few were the winters\n          That the daughter of H�reth had dwelt in the borough;\n       40 But she nowise was cringing nor niggard of presents,\n          Of ornaments rare, to the race of the Geatmen.\n\n{Offa's consort, Thrytho, is contrasted with Hygd.}\n\n          Thrytho nursed anger, excellent[5] folk-queen,\n          Hot-burning hatred: no hero whatever\n          'Mong household companions, her husband excepted\n\n{She is a terror to all save her husband.}\n\n       45 Dared to adventure to look at the woman\n          With eyes in the daytime;[6] but he knew that death-chains\n          Hand-wreathed were wrought him: early thereafter,\n          When the hand-strife was over, edges were ready,\n          That fierce-raging sword-point had to force a decision,\n       50 Murder-bale show. Such no womanly custom\n          For a lady to practise, though lovely her person,\n          That a weaver-of-peace, on pretence of anger\n          A belov�d liegeman of life should deprive.\n          Soothly this hindered Heming's kinsman;\n       55 Other ale-drinking earlmen asserted\n          That fearful folk-sorrows fewer she wrought them,\n          Treacherous doings, since first she was given\n          Adorned with gold to the war-hero youthful,\n          For her origin honored, when Offa's great palace\n       60 O'er the fallow flood by her father's instructions\n          She sought on her journey, where she afterwards fully,\n          Famed for her virtue, her fate on the king's-seat\n[67]      Enjoyed in her lifetime, love did she hold with\n          The ruler of heroes, the best, it is told me,\n       65 Of all of the earthmen that oceans encompass,\n          Of earl-kindreds endless; hence Offa was famous\n          Far and widely, by gifts and by battles,\n          Spear-valiant hero; the home of his fathers\n          He governed with wisdom, whence Eom�r did issue\n       70 For help unto heroes, Heming's kinsman,\n          Grandson of Garmund, great in encounters.\n\n    [1] For 'scawan' (1896), 'sca�an' has been proposed. Accepting this,\n    we may render: _He said the bright-armored warriors were going to\n    their vessel, welcome, etc_. (Cf. 1804.)\n\n    [2] R. suggests, 'Gew�t him on naca,' and renders: _The vessel set\n    out, to drive on the sea, the Dane-country left_. 'On' bears the\n    alliteration; cf. 'on hafu' (2524). This has some advantages over the\n    H.-So. reading; viz. (1) It adds nothing to the text; (2) it makes\n    'naca' the subject, and thus brings the passage into keeping with the\n    context, where the poet has exhausted his vocabulary in detailing the\n    actions of the vessel.--B.'s emendation (cf. P. and B. XII. 97) is\n    violent.\n\n    [3] B. translates: _Who for a long time, ready at the coast, had\n    looked out into the distance eagerly for the dear men_. This changes\n    the syntax of 'l�ofra manna.'\n\n    [4] For 'wuna�' (v. 1924) several eminent critics suggest 'wunade'\n    (=remained). This makes the passage much clearer.\n\n    [5] Why should such a woman be described as an 'excellent' queen? C.\n    suggests 'fr�cnu' = dangerous, bold.\n\n    [6] For 'an d�ges' various readings have been offered. If 'and-�ges'\n    be accepted, the sentence will read: _No hero ... dared look upon her,\n    eye to eye_. If '�n-d�ges' be adopted, translate: _Dared look upon her\n    the whole day_.\n\n\n\n\nXXIX.\n\nBEOWULF AND HIGELAC.\n\n\n          Then the brave one departed, his band along with him,\n\n{Beowulf and his party seek Higelac.}\n\n          Seeking the sea-shore, the sea-marches treading,\n          The wide-stretching shores. The world-candle glimmered,\n          The sun from the southward; they proceeded then onward,\n        5 Early arriving where they heard that the troop-lord,\n          Ongentheow's slayer, excellent, youthful\n          Folk-prince and warrior was distributing jewels,\n          Close in his castle. The coming of Beowulf\n          Was announced in a message quickly to Higelac,\n       10 That the folk-troop's defender forth to the palace\n          The linden-companion alive was advancing,\n          Secure from the combat courtward a-going.\n          The building was early inward made ready\n          For the foot-going guests as the good one had ordered.\n\n{Beowulf sits by his liegelord.}\n\n       15 He sat by the man then who had lived through the struggle,\n          Kinsman by kinsman, when the king of the people\n          Had in lordly language saluted the dear one,\n\n{Queen Hygd receives the heroes.}\n\n          In words that were formal. The daughter of H�reth\n          Coursed through the building, carrying mead-cups:[1]\n[68]   20 She loved the retainers, tendered the beakers\n          To the high-minded Geatmen. Higelac 'gan then\n\n{Higelac is greatly interested in Beowulf's adventures.}\n\n          Pleasantly plying his companion with questions\n          In the high-towering palace. A curious interest\n          Tormented his spirit, what meaning to see in\n       25 The Sea-Geats' adventures: \"Beowulf worthy,\n\n{Give an account of thy adventures, Beowulf dear.}\n\n          How throve your journeying, when thou thoughtest suddenly\n          Far o'er the salt-streams to seek an encounter,\n          A battle at Heorot? Hast bettered for Hrothgar,\n          The famous folk-leader, his far-published sorrows\n       30 Any at all? In agony-billows\n\n{My suspense has been great.}\n\n          I mused upon torture, distrusted the journey\n          Of the belov�d liegeman; I long time did pray thee\n          By no means to seek out the murderous spirit,\n          To suffer the South-Danes themselves to decide on[2]\n       35 Grappling with Grendel. To God I am thankful\n          To be suffered to see thee safe from thy journey.\"\n\n{Beowulf narrates his adventures.}\n\n          Beowulf answered, bairn of old Ecgtheow:\n          \"'Tis hidden by no means, Higelac chieftain,\n          From many of men, the meeting so famous,\n       40 What mournful moments of me and of Grendel\n          Were passed in the place where he pressing affliction\n          On the Victory-Scyldings scathefully brought,\n          Anguish forever; that all I aveng�d,\n          So that any under heaven of the kinsmen of Grendel\n\n{Grendel's kindred have no cause to boast.}\n\n       45 Needeth not boast of that cry-in-the-morning,\n          Who longest liveth of the loth-going kindred,[3]\n          Encompassed by moorland. I came in my journey\n          To the royal ring-hall, Hrothgar to greet there:\n\n{Hrothgar received me very cordially.}\n\n          Soon did the famous scion of Healfdene,\n       50 When he understood fully the spirit that led me,\n          Assign me a seat with the son of his bosom.\n[69]      The troop was in joyance; mead-glee greater\n          'Neath arch of the ether not ever beheld I\n\n{The queen also showed up no little honor.}\n\n          'Mid hall-building holders. The highly-famed queen,\n       55 Peace-tie of peoples, oft passed through the building,\n          Cheered the young troopers; she oft tendered a hero\n          A beautiful ring-band, ere she went to her sitting.\n\n{Hrothgar's lovely daughter.}\n\n          Oft the daughter of Hrothgar in view of the courtiers\n          To the earls at the end the ale-vessel carried,\n       60 Whom Freaware I heard then hall-sitters title,\n          When nail-adorned jewels she gave to the heroes:\n\n{She is betrothed to Ingeld, in order to unite the Danes and Heathobards.}\n\n          Gold-bedecked, youthful, to the glad son of Froda\n          Her faith has been plighted; the friend of the Scyldings,\n          The guard of the kingdom, hath given his sanction,[4]\n       65 And counts it a vantage, for a part of the quarrels,\n          A portion of hatred, to pay with the woman.\n          [5]Somewhere not rarely, when the ruler has fallen,\n          The life-taking lance relaxeth its fury\n          For a brief breathing-spell, though the bride be charming!\n\n    [1] 'Meodu-scencum' (1981) some would render '_with mead-pourers_.'\n    Translate then: _The daughter of H�reth went through the building\n    accompanied by mead-pourers_.\n\n    [2] See my note to 1599, supra, and B. in P. and B. XII. 97.\n\n    [3] For 'fenne,' supplied by Grdtvg., B. suggests 'f�cne' (cf. Jul.\n    350). Accepting this, translate: _Who longest lives of the hated race,\n    steeped in treachery_.\n\n    [4] See note to v. 1599 above.\n\n    [5] This is perhaps the least understood sentence in the poem, almost\n    every word being open to dispute. (1) The 'n�' of our text is an\n    emendation, and is rejected by many scholars. (2) 'Seldan' is by some\n    taken as an adv. (= _seldom_), and by others as a noun (= _page_,\n    _companion_). (3) 'L�od-hryre,' some render '_fall of the people_';\n    others, '_fall of the prince_.' (4) 'B�ge�,' most scholars regard as\n    the intrans. verb meaning '_bend_,' '_rest_'; but one great scholar has\n    translated it '_shall kill_.' (5) 'Hw�r,' Very recently, has been\n    attacked, 'w�re' being suggested. (6) As a corollary to the above, the\n    same critic proposes to drop 'oft' out of the text.--t.B. suggests: Oft\n    seldan w�re after l�odhryre: l�tle hw�le bong�r b�ge�, ��ah s�o br�d\n    duge = _often has a treaty been (thus) struck, after a prince had\n    fallen: (but only) a short time is the spear (then) wont to rest,\n    however excellent the bride may be_.\n\n\n\n\nXXX.\n\nBEOWULF NARRATES HIS ADVENTURES TO HIGELAC.\n\n\n          \"It well may discomfit the prince of the Heathobards\n          And each of the thanemen of earls that attend him,\n[70]      When he goes to the building escorting the woman,\n          That a noble-born Daneman the knights should be feasting:\n        5 There gleam on his person the leavings of elders\n          Hard and ring-bright, Heathobards' treasure,\n          While they wielded their arms, till they misled to the battle\n          Their own dear lives and belov�d companions.\n          He saith at the banquet who the collar beholdeth,\n       10 An ancient ash-warrior who earlmen's destruction\n          Clearly recalleth (cruel his spirit),\n          Sadly beginneth sounding the youthful\n          Thane-champion's spirit through the thoughts of his bosom,\n          War-grief to waken, and this word-answer speaketh:\n\n{Ingeld is stirred up to break the truce.}\n\n       15 'Art thou able, my friend, to know when thou seest it\n          The brand which thy father bare to the conflict\n          In his latest adventure, 'neath visor of helmet,\n          The dearly-loved iron, where Danemen did slay him,\n          And brave-mooded Scyldings, on the fall of the heroes,\n       20 (When vengeance was sleeping) the slaughter-place wielded?\n          E'en now some man of the murderer's progeny\n          Exulting in ornaments enters the building,\n          Boasts of his blood-shedding, offbeareth the jewel\n          Which thou shouldst wholly hold in possession!'\n       25 So he urgeth and mindeth on every occasion\n          With woe-bringing words, till waxeth the season\n          When the woman's thane for the works of his father,\n          The bill having bitten, blood-gory sleepeth,\n          Fated to perish; the other one thenceward\n       30 'Scapeth alive, the land knoweth thoroughly.[1]\n          Then the oaths of the earlmen on each side are broken,\n          When rancors unresting are raging in Ingeld\n          And his wife-love waxeth less warm after sorrow.\n          So the Heathobards' favor not faithful I reckon,\n       35 Their part in the treaty not true to the Danemen,\n          Their friendship not fast. I further shall tell thee\n\n[71]\n\n{Having made these preliminary statements, I will now tell thee of\nGrendel, the monster.}\n\n          More about Grendel, that thou fully mayst hear,\n          Ornament-giver, what afterward came from\n          The hand-rush of heroes. When heaven's bright jewel\n       40 O'er earthfields had glided, the stranger came raging,\n          The horrible night-fiend, us for to visit,\n          Where wholly unharmed the hall we were guarding.\n\n{Hondscio fell first}\n\n          To Hondscio happened a hopeless contention,\n          Death to the doomed one, dead he fell foremost,\n       45 Girded war-champion; to him Grendel became then,\n          To the vassal distinguished, a tooth-weaponed murderer,\n          The well-beloved henchman's body all swallowed.\n          Not the earlier off empty of hand did\n          The bloody-toothed murderer, mindful of evils,\n       50 Wish to escape from the gold-giver's palace,\n          But sturdy of strength he strove to outdo me,\n          Hand-ready grappled. A glove was suspended\n          Spacious and wondrous, in art-fetters fastened,\n          Which was fashioned entirely by touch of the craftman\n       55 From the dragon's skin by the devil's devices:\n          He down in its depths would do me unsadly\n          One among many, deed-doer raging,\n          Though sinless he saw me; not so could it happen\n          When I in my anger upright did stand.\n       60 'Tis too long to recount how requital I furnished\n          For every evil to the earlmen's destroyer;\n\n{I reflected honor upon my people.}\n\n          'Twas there, my prince, that I proudly distinguished\n          Thy land with my labors. He left and retreated,\n          He lived his life a little while longer:\n       65 Yet his right-hand guarded his footstep in Heorot,\n          And sad-mooded thence to the sea-bottom fell he,\n          Mournful in mind. For the might-rush of battle\n\n{King Hrothgar lavished gifts upon me.}\n\n          The friend of the Scyldings, with gold that was plated,\n          With ornaments many, much requited me,\n       70 When daylight had dawned, and down to the banquet\n          We had sat us together. There was chanting and joyance:\n          The age-stricken Scylding asked many questions\n[72]      And of old-times related; oft light-ringing harp-strings,\n          Joy-telling wood, were touched by the brave one;\n       75 Now he uttered measures, mourning and truthful,\n          Then the large-hearted land-king a legend of wonder\n          Truthfully told us. Now troubled with years\n\n{The old king is sad over the loss of his youthful vigor.}\n\n          The age-hoary warrior afterward began to\n          Mourn for the might that marked him in youth-days;\n       80 His breast within boiled, when burdened with winters\n          Much he remembered. From morning till night then\n          We joyed us therein as etiquette suffered,\n          Till the second night season came unto earth-folk.\n          Then early thereafter, the mother of Grendel\n\n{Grendel's mother.}\n\n       85 Was ready for vengeance, wretched she journeyed;\n          Her son had death ravished, the wrath of the Geatmen.\n          The horrible woman aveng�d her offspring,\n          And with mighty mainstrength murdered a hero.\n\n{�schere falls a prey to her vengeance.}\n\n          There the spirit of �schere, ag�d adviser,\n       90 Was ready to vanish; nor when morn had lightened\n          Were they anywise suffered to consume him with fire,\n          Folk of the Danemen, the death-weakened hero,\n          Nor the belov�d liegeman to lay on the pyre;\n\n{She suffered not his body to be burned, but ate it.}\n\n          She the corpse had offcarried in the clutch of the foeman[2]\n       95 'Neath mountain-brook's flood. To Hrothgar 'twas saddest\n          Of pains that ever had preyed on the chieftain;\n          By the life of thee the land-prince then me[3]\n          Besought very sadly, in sea-currents' eddies\n          To display my prowess, to peril my safety,\n      100 Might-deeds accomplish; much did he promise.\n\n{I sought the creature in her den,}\n\n          I found then the famous flood-current's cruel,\n          Horrible depth-warder. A while unto us two\n[73]      Hand was in common; the currents were seething\n          With gore that was clotted, and Grendel's fierce mother's\n\n{and hewed her head off.}\n\n      105 Head I offhacked in the hall at the bottom\n          With huge-reaching sword-edge, hardly I wrested\n          My life from her clutches; not doomed was I then,\n\n{Jewels were freely bestowed upon me.}\n\n          But the warden of earlmen afterward gave me\n          Jewels in quantity, kinsman of Healfdene.\n\n    [1] For 'lifigende' (2063), a mere conjecture, 'w�gende' has been\n    suggested. The line would then read: _Escapeth by fighting, knows the\n    land thoroughly_.\n\n    [2] For 'f��mum,' Gr.'s conjecture, B. proposes 'f�runga.' These three\n    half-verses would then read: _She bore off the corpse of her foe\n    suddenly under the mountain-torrent_.\n\n    [3] The phrase '��ne l�fe' (2132) was long rendered '_with thy\n    (presupposed) permission_.' The verse would read: _The land-prince\n    then sadly besought me, with thy (presupposed) permission, etc_.\n\n\n\n\nXXXI.\n\nGIFT-GIVING IS MUTUAL.\n\n\n          \"So the belov�d land-prince lived in decorum;\n          I had missed no rewards, no meeds of my prowess,\n          But he gave me jewels, regarding my wishes,\n          Healfdene his bairn; I'll bring them to thee, then,\n\n{All my gifts I lay at thy feet.}\n\n        5 Atheling of earlmen, offer them gladly.\n          And still unto thee is all my affection:[1]\n          But few of my folk-kin find I surviving\n          But thee, dear Higelac!\" Bade he in then to carry[2]\n          The boar-image, banner, battle-high helmet,\n       10 Iron-gray armor, the excellent weapon,\n\n{This armor I have belonged of yore to Heregar.}\n\n          In song-measures said: \"This suit-for-the-battle\n          Hrothgar presented me, bade me expressly,\n          Wise-mooded atheling, thereafter to tell thee[3]\n          The whole of its history, said King Heregar owned it,\n       15 Dane-prince for long: yet he wished not to give then\n[74]      The mail to his son, though dearly he loved him,\n          Hereward the hardy. Hold all in joyance!\"\n          I heard that there followed hard on the jewels\n          Two braces of stallions of striking resemblance,\n       20 Dappled and yellow; he granted him usance\n          Of horses and treasures. So a kinsman should bear him,\n          No web of treachery weave for another,\n          Nor by cunning craftiness cause the destruction\n\n{Higelac loves his nephew Beowulf.}\n\n          Of trusty companion. Most precious to Higelac,\n       25 The bold one in battle, was the bairn of his sister,\n          And each unto other mindful of favors.\n\n{Beowulf gives Hygd the necklace that Wealhtheow had given him.}\n\n          I am told that to Hygd he proffered the necklace,\n          Wonder-gem rare that Wealhtheow gave him,\n          The troop-leader's daughter, a trio of horses\n       30 Slender and saddle-bright; soon did the jewel\n          Embellish her bosom, when the beer-feast was over.\n          So Ecgtheow's bairn brave did prove him,\n\n{Beowulf is famous.}\n\n          War-famous man, by deeds that were valiant,\n          He lived in honor, belov�d companions\n       35 Slew not carousing; his mood was not cruel,\n          But by hand-strength hugest of heroes then living\n          The brave one retained the bountiful gift that\n          The Lord had allowed him. Long was he wretched,\n          So that sons of the Geatmen accounted him worthless,\n       40 And the lord of the liegemen loth was to do him\n          Mickle of honor, when mead-cups were passing;\n          They fully believed him idle and sluggish,\n\n{He is requited for the slights suffered in earlier days.}\n\n          An indolent atheling: to the honor-blest man there\n          Came requital for the cuts he had suffered.\n       45 The folk-troop's defender bade fetch to the building\n          The heirloom of Hrethel, embellished with gold,\n\n{Higelac overwhelms the conqueror with gifts.}\n\n          So the brave one enjoined it; there was jewel no richer\n          In the form of a weapon 'mong Geats of that era;\n          In Beowulf's keeping he placed it and gave him\n       50 Seven of thousands, manor and lordship.\n          Common to both was land 'mong the people,\n[75]      Estate and inherited rights and possessions,\n          To the second one specially spacious dominions,\n          To the one who was better. It afterward happened\n       55 In days that followed, befell the battle-thanes,\n\n{After Heardred's death, Beowulf becomes king.}\n\n          After Higelac's death, and when Heardred was murdered\n          With weapons of warfare 'neath well-covered targets,\n          When valiant battlemen in victor-band sought him,\n          War-Scylfing heroes harassed the nephew\n       60 Of Hereric in battle. To Beowulf's keeping\n          Turned there in time extensive dominions:\n\n{He rules the Geats fifty years.}\n\n          He fittingly ruled them a fifty of winters\n          (He a man-ruler wise was, manor-ward old) till\n          A certain one 'gan, on gloom-darkening nights, a\n\n{The fire-drake.}\n\n       65 Dragon, to govern, who guarded a treasure,\n          A high-rising stone-cliff, on heath that was grayish:\n          A path 'neath it lay, unknown unto mortals.\n          Some one of earthmen entered the mountain,\n          The heathenish hoard laid hold of with ardor;\n       70 *�������*�������*�������*�������*�������*�������*\n          *�������*�������*�������*�������*�������*�������*\n          *�������*�������*�������*�������*�������*�������*\n          *�������*�������*�������*�������*�������*�������*\n          *�������*�������*�������*�������*�������*�������*\n\n    [1] This verse B. renders, '_Now serve I again thee alone as my\n    gracious king_.'\n\n    [2] For 'eafor' (2153), Kl. suggests 'ealdor.' Translate then: _Bade\n    the prince then to bear in the banner, battle-high helmet, etc_. On\n    the other hand, W. takes 'eaforh�afodsegn' as a compound, meaning\n    'helmet': _He bade them bear in the helmet, battle-high helm, gray\n    armor, etc_.\n\n    [3] The H.-So. rendering (�rest = _history, origin_; 'eft' for 'est'),\n    though liable to objection, is perhaps the best offered. 'That I\n    should very early tell thee of his favor, kindness' sounds well; but\n    'his' is badly placed to limit '�st.'--Perhaps, 'eft' with verbs of\n    saying may have the force of Lat. prefix 're,' and the H.-So. reading\n    mean, 'that I should its origin rehearse to thee.'\n\n\n\n\nXXXII.\n\nTHE HOARD AND THE DRAGON.\n\n\n          *�������*�������*�������*�������*�������*�������*\n          He sought of himself who sorely did harm him,\n          But, for need very pressing, the servant of one of\n          The sons of the heroes hate-blows evaded,\n        5 Seeking for shelter and the sin-driven warrior\n          Took refuge within there. He early looked in it,\n          *�������*�������*�������*�������*�������*�������*\n          *�������*�������*�������*�������*�������*�������*\n[76]      *��*��*��*��*��*�when the onset surprised him,\n\n{The hoard.}\n\n       10 He a gem-vessel saw there: many of suchlike\n          Ancient ornaments in the earth-cave were lying,\n          As in days of yore some one of men of\n          Illustrious lineage, as a legacy monstrous,\n          There had secreted them, careful and thoughtful,\n       15 Dear-valued jewels. Death had offsnatched them,\n          In the days of the past, and the one man moreover\n          Of the flower of the folk who fared there the longest,\n          Was fain to defer it, friend-mourning warder,\n          A little longer to be left in enjoyment\n       20 Of long-lasting treasure.[1] A barrow all-ready\n          Stood on the plain the stream-currents nigh to,\n          New by the ness-edge, unnethe of approaching:\n          The keeper of rings carried within a\n          [2]Ponderous deal of the treasure of nobles,\n       25 Of gold that was beaten, briefly he spake then:[3]\n\n{The ring-giver bewails the loss of retainers.}\n\n          \"Hold thou, O Earth, now heroes no more may,\n          The earnings of earlmen. Lo! erst in thy bosom\n          Worthy men won them; war-death hath ravished,\n          Perilous life-bale, all my warriors,\n       30 Liegemen belov�d, who this life have forsaken,\n          Who hall-pleasures saw. No sword-bearer have I,\n          And no one to burnish the gold-plated vessel,\n          The high-valued beaker: my heroes are vanished.\n          The hardy helmet behung with gilding\n       35 Shall be reaved of its riches: the ring-cleansers slumber\n          Who were charged to have ready visors-for-battle,\n          And the burnie that bided in battle-encounter\n[77]      O'er breaking of war-shields the bite of the edges\n          Moulds with the hero. The ring-twisted armor,\n       40 Its lord being lifeless, no longer may journey\n          Hanging by heroes; harp-joy is vanished,\n          The rapture of glee-wood, no excellent falcon\n          Swoops through the building, no swift-footed charger\n          Grindeth the gravel. A grievous destruction\n       45 No few of the world-folk widely hath scattered!\"\n          So, woful of spirit one after all\n          Lamented mournfully, moaning in sadness\n          By day and by night, till death with its billows\n\n{The fire-dragon}\n\n          Dashed on his spirit. Then the ancient dusk-scather\n       50 Found the great treasure standing all open,\n          He who flaming and fiery flies to the barrows,\n          Naked war-dragon, nightly escapeth\n          Encompassed with fire; men under heaven\n          Widely beheld him. 'Tis said that he looks for[4]\n       55 The hoard in the earth, where old he is guarding\n          The heathenish treasure; he'll be nowise the better.\n\n{The dragon meets his match.}\n\n          So three-hundred winters the waster of peoples\n          Held upon earth that excellent hoard-hall,\n          Till the forementioned earlman angered him bitterly:\n       60 The beat-plated beaker he bare to his chieftain\n          And fullest remission for all his remissness\n          Begged of his liegelord. Then the hoard[5] was discovered,\n          The treasure was taken, his petition was granted\n\n{The hero plunders the dragon's den}\n\n          The lorn-mooded liegeman. His lord regarded\n       65 The old-work of earth-folk--'twas the earliest occasion.\n          When the dragon awoke, the strife was renewed there;\n          He snuffed 'long the stone then, stout-hearted found he\n[78]      The footprint of foeman; too far had he gone\n          With cunning craftiness close to the head of\n       70 The fire-spewing dragon. So undoomed he may 'scape from\n          Anguish and exile with ease who possesseth\n          The favor of Heaven. The hoard-warden eagerly\n          Searched o'er the ground then, would meet with the person\n          That caused him sorrow while in slumber reclining:\n       75 Gleaming and wild he oft went round the cavern,\n          All of it outward; not any of earthmen\n          Was seen in that desert.[6] Yet he joyed in the battle,\n          Rejoiced in the conflict: oft he turned to the barrow,\n          Sought for the gem-cup;[7] this he soon perceived then\n\n{The dragon perceives that some one has disturbed his treasure.}\n\n       80 That some man or other had discovered the gold,\n          The famous folk-treasure. Not fain did the hoard-ward\n          Wait until evening; then the ward of the barrow\n          Was angry in spirit, the loath�d one wished to\n          Pay for the dear-valued drink-cup with fire.\n       85 Then the day was done as the dragon would have it,\n          He no longer would wait on the wall, but departed\n\n{The dragon is infuriated.}\n\n          Fire-impelled, flaming. Fearful the start was\n          To earls in the land, as it early thereafter\n          To their giver-of-gold was grievously ended.\n\n    [1] For 'long-gestr�ona,' B. suggests 'l�engestr�ona,' and renders,\n    _Of fleeting treasures_. S. accepts H.'s 'long-gestr�ona,' but\n    renders, _The treasure long in accumulating_.\n\n    [2] For 'hard-fyrdne' (2246), B. first suggested 'hard-fyndne,'\n    rendering: _A heap of treasures ... so great that its equal would be\n    hard to find_. The same scholar suggests later 'hord-wynne d�l' = _A\n    deal of treasure-joy_.\n\n    [3] Some read 'fec-word' (2247), and render: _Banning words uttered_.\n\n    [4] An earlier reading of H.'s gave the following meaning to this\n    passage: _He is said to inhabit a mound under the earth, where he,\n    etc._ The translation in the text is more authentic.\n\n    [5] The repetition of 'hord' in this passage has led some scholars to\n    suggest new readings to avoid the second 'hord.' This, however, is not\n    under the main stress, and, it seems to me, might easily be accepted.\n\n    [6] The reading of H.-So. is well defended in the notes to that\n    volume. B. emends and renders: _Nor was there any man in that desert\n    who rejoiced in conflict, in battle-work._ That is, the hoard-ward\n    could not find any one who had disturbed his slumbers, for no warrior\n    was there, t.B.'s emendation would give substantially the same\n    translation.\n\n    [7] 'Sinc-f�t' (2301): this word both here and in v. 2232, t.B.\n    renders 'treasure.'\n\n\n\n\nXXXIII.\n\nBRAVE THOUGH AGED.--REMINISCENCES.\n\n\n{The dragon spits fire.}\n\n          The stranger began then to vomit forth fire,\n          To burn the great manor; the blaze then glimmered\n          For anguish to earlmen, not anything living\n[79]      Was the hateful air-goer willing to leave there.\n        5 The war of the worm widely was noticed,\n          The feud of the foeman afar and anear,\n          How the enemy injured the earls of the Geatmen,\n          Harried with hatred: back he hied to the treasure,\n          To the well-hidden cavern ere the coming of daylight.\n       10 He had circled with fire the folk of those regions,\n          With brand and burning; in the barrow he trusted,\n          In the wall and his war-might: the weening deceived him.\n\n{Beowulf hears of the havoc wrought by the dragon.}\n\n          Then straight was the horror to Beowulf published,\n          Early forsooth, that his own native homestead,[1]\n       15 The best of buildings, was burning and melting,\n          Gift-seat of Geatmen. 'Twas a grief to the spirit\n          Of the good-mooded hero, the greatest of sorrows:\n\n{He fears that Heaven is punishing him for some crime.}\n\n          The wise one weened then that wielding his kingdom\n          'Gainst the ancient commandments, he had bitterly angered\n       20 The Lord everlasting: with lorn meditations\n          His bosom welled inward, as was nowise his custom.\n          The fire-spewing dragon fully had wasted\n          The fastness of warriors, the water-land outward,\n          The manor with fire. The folk-ruling hero,\n       25 Prince of the Weders, was planning to wreak him.\n          The warmen's defender bade them to make him,\n          Earlmen's atheling, an excellent war-shield\n\n{He orders an iron shield to be made from him, wood is useless.}\n\n          Wholly of iron: fully he knew then\n          That wood from the forest was helpless to aid him,\n       30 Shield against fire. The long-worthy ruler\n          Must live the last of his limited earth-days,\n          Of life in the world and the worm along with him,\n          Though he long had been holding hoard-wealth in plenty.\n\n{He determines to fight alone.}\n\n          Then the ring-prince disdained to seek with a war-band,\n       35 With army extensive, the air-going ranger;\n          He felt no fear of the foeman's assaults and\n          He counted for little the might of the dragon,\n[80]      His power and prowess: for previously dared he\n\n{Beowulf's early triumphs referred to}\n\n          A heap of hostility, hazarded dangers,\n       40 War-thane, when Hrothgar's palace he cleans�d,\n          Conquering combatant, clutched in the battle\n          The kinsmen of Grendel, of kindred detested.[2]\n\n{Higelac's death recalled.}\n\n          'Twas of hand-fights not least where Higelac was slaughtered,\n          When the king of the Geatmen with clashings of battle,\n       45 Friend-lord of folks in Frisian dominions,\n          Offspring of Hrethrel perished through sword-drink,\n          With battle-swords beaten; thence Beowulf came then\n          On self-help relying, swam through the waters;\n          He bare on his arm, lone-going, thirty\n       50 Outfits of armor, when the ocean he mounted.\n          The Hetwars by no means had need to be boastful\n          Of their fighting afoot, who forward to meet him\n          Carried their war-shields: not many returned from\n          The brave-mooded battle-knight back to their homesteads.\n       55 Ecgtheow's bairn o'er the bight-courses swam then,\n          Lone-goer lorn to his land-folk returning,\n          Where Hygd to him tendered treasure and kingdom,\n\n{Heardred's lack of capacity to rule.}\n\n          Rings and dominion: her son she not trusted,\n          To be able to keep the kingdom devised him\n       60 'Gainst alien races, on the death of King Higelac.\n\n{Beowulf's tact and delicacy recalled.}\n\n          Yet the sad ones succeeded not in persuading the atheling\n          In any way ever, to act as a suzerain\n          To Heardred, or promise to govern the kingdom;\n          Yet with friendly counsel in the folk he sustained him,\n       65 Gracious, with honor, till he grew to be older,\n\n{Reference is here made to a visit which Beowulf receives from Eanmund and\nEadgils, why they come is not known.}\n\n          Wielded the Weders. Wide-fleeing outlaws,\n          Ohthere's sons, sought him o'er the waters:\n          They had stirred a revolt 'gainst the helm of the Scylfings,\n          The best of the sea-kings, who in Swedish dominions\n       70 Distributed treasure, distinguished folk-leader.\n[81]      'Twas the end of his earth-days; injury fatal[3]\n          By swing of the sword he received as a greeting,\n          Offspring of Higelac; Ongentheow's bairn\n          Later departed to visit his homestead,\n       75 When Heardred was dead; let Beowulf rule them,\n          Govern the Geatmen: good was that folk-king.\n\n    [1] 'H�m' (2326), the suggestion of B. is accepted by t.B. and other\n    scholars.\n\n    [2] For 'l��an cynnes' (2355), t.B. suggests 'l��an cynne,' apposition\n    to 'm�gum.' From syntactical and other considerations, this is a most\n    excellent emendation.\n\n    [3] Gr. read 'on feorme' (2386), rendering: _He there at the banquet a\n    fatal wound received by blows of the sword._\n\n\n\n\nXXXIV.\n\nBEOWULF SEEKS THE DRAGON.--BEOWULF'S REMINISCENCES.\n\n\n          He planned requital for the folk-leader's ruin\n          In days thereafter, to Eadgils the wretched\n          Becoming an enemy. Ohthere's son then\n          Went with a war-troop o'er the wide-stretching currents\n        5 With warriors and weapons: with woe-journeys cold he\n          After avenged him, the king's life he took.\n\n{Beowulf has been preserved through many perils.}\n\n          So he came off uninjured from all of his battles,\n          Perilous fights, offspring of Ecgtheow,\n          From his deeds of daring, till that day most momentous\n       10 When he fate-driven fared to fight with the dragon.\n\n{With eleven comrades, he seeks the dragon.}\n\n          With eleven companions the prince of the Geatmen\n          Went lowering with fury to look at the fire-drake:\n          Inquiring he'd found how the feud had arisen,\n          Hate to his heroes; the highly-famed gem-vessel\n       15 Was brought to his keeping through the hand of th' informer.\n\n{A guide leads the way, but}\n\n          That in the throng was thirteenth of heroes,\n          That caused the beginning of conflict so bitter,\n          Captive and wretched, must sad-mooded thenceward\n\n{very reluctantly.}\n\n          Point out the place: he passed then unwillingly\n       20 To the spot where he knew of the notable cavern,\n          The cave under earth, not far from the ocean,\n          The anger of eddies, which inward was full of\n          Jewels and wires: a warden uncanny,\n[82]      Warrior weaponed, wardered the treasure,\n       25 Old under earth; no easy possession\n          For any of earth-folk access to get to.\n          Then the battle-brave atheling sat on the naze-edge,\n          While the gold-friend of Geatmen gracious saluted\n          His fireside-companions: woe was his spirit,\n       30 Death-boding, wav'ring; Weird very near him,\n          Who must seize the old hero, his soul-treasure look for,\n          Dragging aloof his life from his body:\n          Not flesh-hidden long was the folk-leader's spirit.\n          Beowulf spake, Ecgtheow's son:\n\n{Beowulf's retrospect.}\n\n       35 \"I survived in my youth-days many a conflict,\n          Hours of onset: that all I remember.\n          I was seven-winters old when the jewel-prince took me,\n          High-lord of heroes, at the hands of my father,\n          Hrethel the hero-king had me in keeping,\n\n{Hrethel took me when I was seven.}\n\n       40 Gave me treasure and feasting, our kinship remembered;\n          Not ever was I _any_ less dear to him\n\n{He treated me as a son.}\n\n          Knight in the boroughs, than the bairns of his household,\n          Herebald and H�thcyn and Higelac mine.\n          To the eldest unjustly by acts of a kinsman\n       45 Was murder-bed strewn, since him H�thcyn from horn-bow\n\n{One of the brothers accidentally kills another.}\n\n          His sheltering chieftain shot with an arrow,\n          Erred in his aim and injured his kinsman,\n          One brother the other, with blood-sprinkled spear:\n\n{No fee could compound for such a calamity.}\n\n          'Twas a feeless fight, finished in malice,\n       50 Sad to his spirit; the folk-prince however\n          Had to part from existence with vengeance untaken.\n\n{[A parallel case is supposed.]}\n\n          So to hoar-headed hero 'tis heavily crushing[1]\n[83]      To live to see his son as he rideth\n          Young on the gallows: then measures he chanteth,\n       55 A song of sorrow, when his son is hanging\n          For the raven's delight, and aged and hoary\n          He is unable to offer any assistance.\n          Every morning his offspring's departure\n          Is constant recalled: he cares not to wait for\n       60 The birth of an heir in his borough-enclosures,\n          Since that one through death-pain the deeds hath experienced.\n          He heart-grieved beholds in the house of his son the\n          Wine-building wasted, the wind-lodging places\n          Reaved of their roaring; the riders are sleeping,\n       65 The knights in the grave; there's no sound of the harp-wood,\n          Joy in the yards, as of yore were familiar.\n\n    [1] 'Gomelum ceorle' (2445).--H. takes these words as referring to\n    Hrethel; but the translator here departs from his editor by\n    understanding the poet to refer to a hypothetical old man, introduced\n    as an illustration of a father's sorrow.\n\n    Hrethrel had certainly never seen a son of his ride on the gallows to\n    feed the crows.\n\n    The passage beginning 'sw� bi� g�omorlic' seems to be an effort to\n    reach a full simile, 'as ... so.' 'As it is mournful for an old man,\n    etc. ... so the defence of the Weders (2463) bore heart-sorrow, etc.'\n    The verses 2451 to 2463-1/2 would be parenthetical, the poet's feelings\n    being so strong as to interrupt the simile. The punctuation of the\n    fourth edition would be better--a comma after 'galgan' (2447). The\n    translation may be indicated as follows: _(Just) as it is sad for an\n    old man to see his son ride young on the gallows when he himself is\n    uttering mournful measures, a sorrowful song, while his son hangs for a\n    comfort to the raven, and he, old and infirm, cannot render him any\n    kelp--(he is constantly reminded, etc., 2451-2463)--so the defence of\n    the Weders, etc._\n\n\n\n\nXXXV.\n\nREMINISCENCES (_continued_).--BEOWULF'S LAST BATTLE.\n\n\n          \"He seeks then his chamber, singeth a woe-song\n          One for the other; all too extensive\n          Seemed homesteads and plains. So the helm of the Weders\n\n{Hrethel grieves for Herebald.}\n\n          Mindful of Herebald heart-sorrow carried,\n        5 Stirred with emotion, nowise was able\n          To wreak his ruin on the ruthless destroyer:\n          He was unable to follow the warrior with hatred,\n          With deeds that were direful, though dear he not held him.\n[84]      Then pressed by the pang this pain occasioned him,\n       10 He gave up glee, God-light elected;\n          He left to his sons, as the man that is rich does,\n          His land and fortress, when from life he departed.\n\n{Strife between Swedes and Geats.}\n\n          Then was crime and hostility 'twixt Swedes and Geatmen,\n          O'er wide-stretching water warring was mutual,\n       15 Burdensome hatred, when Hrethel had perished,\n          And Ongentheow's offspring were active and valiant,\n          Wished not to hold to peace oversea, but\n          Round Hreosna-beorh often accomplished\n          Cruelest massacre. This my kinsman aveng�d,\n       20 The feud and fury, as 'tis found on inquiry,\n          Though one of them paid it with forfeit of life-joys,\n\n{H�thcyn's fall at Ravenswood.}\n\n          With price that was hard: the struggle became then\n          Fatal to H�thcyn, lord of the Geatmen.\n          Then I heard that at morning one brother the other\n       25 With edges of irons egged on to murder,\n          Where Ongentheow maketh onset on Eofor:\n          The helmet crashed, the hoary-haired Scylfing\n          Sword-smitten fell, his hand then remembered\n          Feud-hate sufficient, refused not the death-blow.\n\n{I requited him for the jewels he gave me.}\n\n       30 The gems that he gave me, with jewel-bright sword I\n          'Quited in contest, as occasion was offered:\n          Land he allowed me, life-joy at homestead,\n          Manor to live on. Little he needed\n          From Gepids or Danes or in Sweden to look for\n       35 Trooper less true, with treasure to buy him;\n          'Mong foot-soldiers ever in front I would hie me,\n          Alone in the vanguard, and evermore gladly\n          Warfare shall wage, while this weapon endureth\n          That late and early often did serve me\n\n{Beowulf refers to his having slain D�ghrefn.}\n\n       40 When I proved before heroes the slayer of D�ghrefn,\n          Knight of the Hugmen: he by no means was suffered\n          To the king of the Frisians to carry the jewels,\n          The breast-decoration; but the banner-possessor\n          Bowed in the battle, brave-mooded atheling.\n[85]   45 No weapon was slayer, but war-grapple broke then\n          The surge of his spirit, his body destroying.\n          Now shall weapon's edge make war for the treasure,\n          And hand and firm-sword.\" Beowulf spake then,\n          Boast-words uttered--the latest occasion:\n\n{He boasts of his youthful prowess, and declares himself still fearless.}\n\n       50 \"I braved in my youth-days battles unnumbered;\n          Still am I willing the struggle to look for,\n          Fame-deeds perform, folk-warden prudent,\n          If the hateful despoiler forth from his cavern\n          Seeketh me out!\" Each of the heroes,\n       55 Helm-bearers sturdy, he thereupon greeted\n\n{His last salutations.}\n\n          Belov�d co-liegemen--his last salutation:\n          \"No brand would I bear, no blade for the dragon,\n          Wist I a way my word-boast to 'complish[1]\n          Else with the monster, as with Grendel I did it;\n       60 But fire in the battle hot I expect there,\n          Furious flame-burning: so I fixed on my body\n          Target and war-mail. The ward of the barrow[2]\n          I'll not flee from a foot-length, the foeman uncanny.\n          At the wall 'twill befall us as Fate decreeth,\n\n{Let Fate decide between us.}\n\n       65 Each one's Creator. I am eager in spirit,\n          With the wing�d war-hero to away with all boasting.\n          Bide on the barrow with burnies protected,\n\n{Wait ye here till the battle is over.}\n\n          Earls in armor, which of _us_ two may better\n          Bear his disaster, when the battle is over.\n       70 'Tis no matter of yours, and man cannot do it,\n          But me and me only, to measure his strength with\n          The monster of malice, might-deeds to 'complish.\n          I with prowess shall gain the gold, or the battle,\n[86]      Direful death-woe will drag off your ruler!\"\n       75 The mighty champion rose by his shield then,\n          Brave under helmet, in battle-mail went he\n          'Neath steep-rising stone-cliffs, the strength he relied on\n          Of one man alone: no work for a coward.\n          Then he saw by the wall who a great many battles\n       80 Had lived through, most worthy, when foot-troops collided,\n\n{The place of strife is described.}\n\n          Stone-arches standing, stout-hearted champion,\n          Saw a brook from the barrow bubbling out thenceward:\n          The flood of the fountain was fuming with war-flame:\n          Not nigh to the hoard, for season the briefest\n       85 Could he brave, without burning, the abyss that was yawning,\n          The drake was so fiery. The prince of the Weders\n          Caused then that words came from his bosom,\n          So fierce was his fury; the firm-hearted shouted:\n          His battle-clear voice came in resounding\n       90 'Neath the gray-colored stone. Stirred was his hatred,\n\n{Beowulf calls out under the stone arches.}\n\n          The hoard-ward distinguished the speech of a man;\n          Time was no longer to look out for friendship.\n          The breath of the monster issued forth first,\n          Vapory war-sweat, out of the stone-cave:\n\n{The terrible encounter.}\n\n       95 The earth re-echoed. The earl 'neath the barrow\n          Lifted his shield, lord of the Geatmen,\n          Tow'rd the terrible stranger: the ring-twisted creature's\n          Heart was then ready to seek for a struggle.\n\n{Beowulf brandishes his sword,}\n\n          The excellent battle-king first brandished his weapon,\n      100 The ancient heirloom, of edges unblunted,[3]\n          To the death-planners twain was terror from other.\n\n{and stands against his shield.}\n\n          The lord of the troopers intrepidly stood then\n          'Gainst his high-rising shield, when the dragon coiled him\n\n{The dragon coils himself.}\n\n          Quickly together: in corslet he bided.\n[87]  105 He went then in blazes, bended and striding,\n          Hasting him forward. His life and body\n          The targe well protected, for time-period shorter\n          Than wish demanded for the well-renowned leader,\n          Where he then for the first day was forced to be victor,\n      110 Famous in battle, as Fate had not willed it.\n          The lord of the Geatmen uplifted his hand then,\n          Smiting the fire-drake with sword that was precious,\n          That bright on the bone the blade-edge did weaken,\n          Bit more feebly than his folk-leader needed,\n      115 Burdened with bale-griefs. Then the barrow-protector,\n\n{The dragon rages}\n\n          When the sword-blow had fallen, was fierce in his spirit,\n          Flinging his fires, flamings of battle\n          Gleamed then afar: the gold-friend of Weders\n\n{Beowulf's sword fails him.}\n\n          Boasted no conquests, his battle-sword failed him\n      120 Naked in conflict, as by no means it ought to,\n          Long-trusty weapon. 'Twas no slight undertaking\n          That Ecgtheow's famous offspring would leave\n          The drake-cavern's bottom; he must live in some region\n          Other than this, by the will of the dragon,\n      125 As each one of earthmen existence must forfeit.\n          'Twas early thereafter the excellent warriors\n\n{The combat is renewed.}\n\n          Met with each other. Anew and afresh\n          The hoard-ward took heart (gasps heaved then his bosom):\n\n{The great hero is reduced to extremities.}\n\n          Sorrow he suffered encircled with fire\n      130 Who the people erst governed. His companions by no means\n          Were banded about him, bairns of the princes,\n\n{His comrades flee!}\n\n          With valorous spirit, but they sped to the forest,\n          Seeking for safety. The soul-deeps of one were\n\n{Blood is thicker than water.}\n\n          Ruffled by care: kin-love can never\n      135 Aught in him waver who well doth consider.\n\n[88]\n\n    [1] The clause 2520(2)-2522(1), rendered by 'Wist I ... monster,' Gr.,\n    followed by S., translates substantially as follows: _If I knew how\n    else I might combat the boastful defiance of the monster_.--The\n    translation turns upon 'wi�gr�pan,' a word not understood.\n\n    [2] B. emends and translates: _I will not flee the space of a foot\n    from the guard of the barrow, but there shall be to us a fight at the\n    wall, as fate decrees, each one's Creator._\n\n    [3] The translation of this passage is based on 'unsl�w' (2565),\n    accepted by H.-So., in lieu of the long-standing 'ungl�aw.' The former\n    is taken as an adj. limiting 'sweord'; the latter as an adj. c.\n    'g��-cyning': _The good war-king, rash with edges, brandished his\n    sword, his old relic._ The latter gives a more rhetorical Anglo-Saxon\n    (poetical) sentence.\n\n\n\n\nXXXVI.\n\nWIGLAF THE TRUSTY.--BEOWULF IS DESERTED BY FRIENDS AND BY SWORD.\n\n\n{Wiglaf remains true--the ideal Teutonic liegeman.}\n\n          The son of Weohstan was Wiglaf entitled,\n          Shield-warrior precious, prince of the Scylfings,\n          �lfhere's kinsman: he saw his dear liegelord\n          Enduring the heat 'neath helmet and visor.\n        5 Then he minded the holding that erst he had given him,\n\n{Wiglaf recalls Beowulf's generosity.}\n\n          The W�gmunding warriors' wealth-bless�d homestead,\n          Each of the folk-rights his father had wielded;\n          He was hot for the battle, his hand seized the target,\n          The yellow-bark shield, he unsheathed his old weapon,\n       10 Which was known among earthmen as the relic of Eanmund,\n          Ohthere's offspring, whom, exiled and friendless,\n          Weohstan did slay with sword-edge in battle,\n          And carried his kinsman the clear-shining helmet,\n          The ring-made burnie, the old giant-weapon\n       15 That Onela gave him, his boon-fellow's armor,\n          Ready war-trappings: he the feud did not mention,\n          Though he'd fatally smitten the son of his brother.\n          Many a half-year held he the treasures,\n          The bill and the burnie, till his bairn became able,\n       20 Like his father before him, fame-deeds to 'complish;\n          Then he gave him 'mong Geatmen a goodly array of\n          Weeds for his warfare; he went from life then\n          Old on his journey. 'Twas the earliest time then\n\n{This is Wiglaf's first battle as liegeman of Beowulf.}\n\n          That the youthful champion might charge in the battle\n       25 Aiding his liegelord; his spirit was dauntless.\n          Nor did kinsman's bequest quail at the battle:\n          This the dragon discovered on their coming together.\n          Wiglaf uttered many a right-saying,\n          Said to his fellows, sad was his spirit:\n\n{Wiglaf appeals to the pride of the cowards.}\n\n       30 \"I remember the time when, tasting the mead-cup,\n          We promised in the hall the lord of us all\n[89]      Who gave us these ring-treasures, that this battle-equipment,\n          Swords and helmets, we'd certainly quite him,\n          Should need of such aid ever befall him:\n\n{How we have forfeited our liegelord's confidence!}\n\n       35 In the war-band he chose us for this journey spontaneously,\n          Stirred us to glory and gave me these jewels,\n          Since he held and esteemed us trust-worthy spearmen,\n          Hardy helm-bearers, though this hero-achievement\n          Our lord intended alone to accomplish,\n       40 Ward of his people, for most of achievements,\n          Doings audacious, he did among earth-folk.\n\n{Our lord is in sore need of us.}\n\n          The day is now come when the ruler of earthmen\n          Needeth the vigor of valiant heroes:\n          Let us wend us towards him, the war-prince to succor,\n       45 While the heat yet rageth, horrible fire-fight.\n\n{I would rather die than go home with out my suzerain.}\n\n          God wot in me, 'tis mickle the liefer\n          The blaze should embrace my body and eat it\n          With my treasure-bestower. Meseemeth not proper\n          To bear our battle-shields back to our country,\n       50 'Less first we are able to fell and destroy the\n          Long-hating foeman, to defend the life of\n\n{Surely he does not deserve to die alone.}\n\n          The prince of the Weders. Well do I know 'tisn't\n          Earned by his exploits, he only of Geatmen\n          Sorrow should suffer, sink in the battle:\n       55 Brand and helmet to us both shall be common,\n          [1]Shield-cover, burnie.\" Through the bale-smoke he stalked then,\n          Went under helmet to the help of his chieftain,\n\n{Wiglaf reminds Beowulf of his youthful boasts.}\n\n          Briefly discoursing: \"Beowulf dear,\n          Perform thou all fully, as thou formerly saidst,\n       60 In thy youthful years, that while yet thou livedst\n[90]      Thou wouldst let thine honor not ever be lessened.\n          Thy life thou shalt save, mighty in actions,\n          Atheling undaunted, with all of thy vigor;\n\n{The monster advances on them.}\n\n          I'll give thee assistance.\" The dragon came raging,\n       65 Wild-mooded stranger, when these words had been uttered\n          ('Twas the second occasion), seeking his enemies,\n          Men that were hated, with hot-gleaming fire-waves;\n          With blaze-billows burned the board to its edges:\n          The fight-armor failed then to furnish assistance\n       70 To the youthful spear-hero: but the young-ag�d stripling\n          Quickly advanced 'neath his kinsman's war-target,\n          Since his own had been ground in the grip of the fire.\n\n{Beowulf strikes at the dragon.}\n\n          Then the warrior-king was careful of glory,\n          He soundly smote with sword-for-the-battle,\n       75 That it stood in the head by hatred driven;\n          N�gling was shivered, the old and iron-made\n\n{His sword fails him.}\n\n          Brand of Beowulf in battle deceived him.\n          'Twas denied him that edges of irons were able\n          To help in the battle; the hand was too mighty\n       80 [2]Which every weapon, as I heard on inquiry,\n          Outstruck in its stroke, when to struggle he carried\n          The wonderful war-sword: it waxed him no better.\n\n{The dragon advances on Beowulf again.}\n\n          Then the people-despoiler--third of his onsets--\n          Fierce-raging fire-drake, of feud-hate was mindful,\n       85 Charged on the strong one, when chance was afforded,\n          Heated and war-grim, seized on his neck\n          With teeth that were bitter; he bloody did wax with\n          Soul-gore seething; sword-blood in waves boiled.\n\n    [1] The passage '_Brand ... burnie_,' is much disputed. In the first\n    place, some eminent critics assume a gap of at least two\n    half-verses.--'�rum' (2660), being a peculiar form, has been much\n    discussed. 'Byrdu-scr�d' is also a crux. B. suggests 'b�wdu-scr�d' =\n    _splendid vestments_. Nor is 'b�m' accepted by all, 'b�on' being\n    suggested. Whatever the individual words, the passage must mean, \"_I\n    intend to share with him my equipments of defence_.\"\n\n    [2] B. would render: _Which, as I heard, excelled in stroke every\n    sword that he carried to the strife, even the strongest (sword)._ For\n    '�onne' he reads '�one,' rel. pr.\n\n[91]\n\n\n\n\nXXXVII.\n\nTHE FATAL STRUGGLE.--BEOWULF'S LAST MOMENTS.\n\n\n{Wiglaf defends Beowulf.}\n\n          Then I heard that at need of the king of the people\n          The upstanding earlman exhibited prowess,\n          Vigor and courage, as suited his nature;\n          [1]He his head did not guard, but the high-minded liegeman's\n        5 Hand was consumed, when he succored his kinsman,\n          So he struck the strife-bringing strange-comer lower,\n          Earl-thane in armor, that _in_ went the weapon\n          Gleaming and plated, that 'gan then the fire[2]\n\n{Beowulf draws his knife,}\n\n          Later to lessen. The liegelord himself then\n       10 Retained his consciousness, brandished his war-knife,\n          Battle-sharp, bitter, that he bare on his armor:\n\n{and cuts the dragon.}\n\n          The Weder-lord cut the worm in the middle.\n          They had felled the enemy (life drove out then[3]\n          Puissant prowess), the pair had destroyed him,\n       15 Land-chiefs related: so a liegeman should prove him,\n          A thaneman when needed. To the prince 'twas the last of\n          His era of conquest by his own great achievements,\n\n[92]\n\n{Beowulf's wound swells and burns.}\n\n          The latest of world-deeds. The wound then began\n          Which the earth-dwelling dragon erstwhile had wrought him\n       20 To burn and to swell. He soon then discovered\n          That bitterest bale-woe in his bosom was raging,\n          Poison within. The atheling advanced then,\n\n{He sits down exhausted.}\n\n          That along by the wall, he prudent of spirit\n          Might sit on a settle; he saw the giant-work,\n       25 How arches of stone strengthened with pillars\n          The earth-hall eternal inward supported.\n          Then the long-worthy liegeman laved with his hand the\n\n{Wiglaf bathes his lord's head.}\n\n          Far-famous chieftain, gory from sword-edge,\n          Refreshing the face of his friend-lord and ruler,\n       30 Sated with battle, unbinding his helmet.\n          Beowulf answered, of his injury spake he,\n          His wound that was fatal (he was fully aware\n          He had lived his allotted life-days enjoying\n          The pleasures of earth; then past was entirely\n       35 His measure of days, death very near):\n\n{Beowulf regrets that he has no son.}\n\n          \"My son I would give now my battle-equipments,\n          Had any of heirs been after me granted,\n          Along of my body. This people I governed\n          Fifty of winters: no king 'mong my neighbors\n       40 Dared to encounter me with comrades-in-battle,\n          Try me with terror. The time to me ordered\n          I bided at home, mine own kept fitly,\n          Sought me no snares, swore me not many\n\n{I can rejoice in a well-spent life.}\n\n          Oaths in injustice. Joy over all this\n       45 I'm able to have, though ill with my death-wounds;\n          Hence the Ruler of Earthmen need not charge me\n          With the killing of kinsmen, when cometh my life out\n          Forth from my body. Fare thou with haste now\n\n{Bring me the hoard, Wiglaf, that my dying eyes may be refreshed by a\nsight of it.}\n\n          To behold the hoard 'neath the hoar-grayish stone,\n       50 Well-lov�d Wiglaf, now the worm is a-lying,\n          Sore-wounded sleepeth, disseized of his treasure.\n          Go thou in haste that treasures of old I,\n          Gold-wealth may gaze on, together see lying\n[93]      The ether-bright jewels, be easier able,\n       55 Having the heap of hoard-gems, to yield my\n          Life and the land-folk whom long I have governed.\"\n\n    [1] B. renders: _He_ (_W_.) did not regard his (_the dragon's_) _head_\n    (since Beowulf had struck it without effect), _but struck the dragon a\n    little lower down.--_One crux is to find out _whose head_ is meant;\n    another is to bring out the antithesis between 'head' and 'hand.'\n\n    [2] '��t ��t f�r' (2702), S. emends to '�� ��t f�r' = _when the fire\n    began to grow less intense afterward_. This emendation relieves the\n    passage of a plethora of conjunctive _��t_'s.\n\n    [3] For 'gefyldan' (2707), S. proposes 'gefylde.' The passage would\n    read: _He felled the foe (life drove out strength), and they then both\n    had destroyed him, chieftains related_. This gives Beowulf the credit\n    of having felled the dragon; then they combine to annihilate him.--For\n    'ellen' (2707), Kl. suggests 'e(a)llne.'--The reading '_life drove out\n    strength_' is very unsatisfactory and very peculiar. I would suggest\n    as follows: Adopt S.'s emendation, remove H.'s parenthesis, read\n    'ferh-ellen wr�c,' and translate: _He felled the foe, drove out his\n    life-strength_ (that is, made him _hors de combat_), _and then they\n    both, etc_.\n\n\n\n\nXXXVIII.\n\nWIGLAF PLUNDERS THE DRAGON'S DEN.--BEOWULF'S DEATH.\n\n\n{Wiglaf fulfils his lord's behest.}\n\n          Then heard I that Wihstan's son very quickly,\n          These words being uttered, heeded his liegelord\n          Wounded and war-sick, went in his armor,\n          His well-woven ring-mail, 'neath the roof of the barrow.\n        5 Then the trusty retainer treasure-gems many\n\n{The dragon's den.}\n\n          Victorious saw, when the seat he came near to,\n          Gold-treasure sparkling spread on the bottom,\n          Wonder on the wall, and the worm-creature's cavern,\n          The ancient dawn-flier's, vessels a-standing,\n       10 Cups of the ancients of cleansers bereav�d,\n          Robbed of their ornaments: there were helmets in numbers,\n          Old and rust-eaten, arm-bracelets many,\n          Artfully woven. Wealth can easily,\n          Gold on the sea-bottom, turn into vanity[1]\n       15 Each one of earthmen, arm him who pleaseth!\n          And he saw there lying an all-golden banner\n          High o'er the hoard, of hand-wonders greatest,\n          Link�d with lacets: a light from it sparkled,\n          That the floor of the cavern he was able to look on,\n\n{The dragon is not there.}\n\n       20 To examine the jewels. Sight of the dragon\n[94]      Not any was offered, but edge offcarried him.\n\n{Wiglaf bears the hoard away.}\n\n          Then I heard that the hero the hoard-treasure plundered,\n          The giant-work ancient reaved in the cavern,\n          Bare on his bosom the beakers and platters,\n       25 As himself would fain have it, and took off the standard,\n          The brightest of beacons;[2] the bill had erst injured\n          (Its edge was of iron), the old-ruler's weapon,\n          Him who long had watched as ward of the jewels,\n          Who fire-terror carried hot for the treasure,\n       30 Rolling in battle, in middlemost darkness,\n          Till murdered he perished. The messenger hastened,\n          Not loth to return, hurried by jewels:\n          Curiosity urged him if, excellent-mooded,\n          Alive he should find the lord of the Weders\n       35 Mortally wounded, at the place where he left him.\n          'Mid the jewels he found then the famous old chieftain,\n          His liegelord belov�d, at his life's-end gory:\n          He thereupon 'gan to lave him with water,\n          Till the point of his word pierc�d his breast-hoard.\n       40 Beowulf spake (the gold-gems he noticed),\n\n{Beowulf is rejoiced to see the jewels.}\n\n          The old one in sorrow: \"For the jewels I look on\n          Thanks do I utter for all to the Ruler,\n          Wielder of Worship, with words of devotion,\n          The Lord everlasting, that He let me such treasures\n       45 Gain for my people ere death overtook me.\n          Since I've bartered the ag�d life to me granted\n          For treasure of jewels, attend ye henceforward\n\n{He desires to be held in memory by his people.}\n\n          The wants of the war-thanes; I can wait here no longer.\n          The battle-famed bid ye to build them a grave-hill,\n       50 Bright when I'm burned, at the brim-current's limit;\n          As a memory-mark to the men I have governed,\n[95]      Aloft it shall tower on Whale's-Ness uprising,\n          That earls of the ocean hereafter may call it\n          Beowulf's barrow, those who barks ever-dashing\n       55 From a distance shall drive o'er the darkness of waters.\"\n\n{The hero's last gift}\n\n          The bold-mooded troop-lord took from his neck then\n          The ring that was golden, gave to his liegeman,\n          The youthful war-hero, his gold-flashing helmet,\n          His collar and war-mail, bade him well to enjoy them:\n\n{and last words.}\n\n       60 \"Thou art latest left of the line of our kindred,\n          Of W�gmunding people: Weird hath offcarried\n          All of my kinsmen to the Creator's glory,\n          Earls in their vigor: I shall after them fare.\"\n          'Twas the aged liegelord's last-spoken word in\n       65 His musings of spirit, ere he mounted the fire,\n          The battle-waves burning: from his bosom departed\n          His soul to seek the sainted ones' glory.\n\n    [1] The word 'oferh�gian' (2767) being vague and little understood,\n    two quite distinct translations of this passage have arisen. One takes\n    'oferh�gian' as meaning 'to exceed,' and, inserting 'hord' after\n    'gehwone,' renders: _The treasure may easily, the gold in the ground,\n    exceed in value every hoard of man, hide it who will._ The other takes\n    'oferh�gian' as meaning 'to render arrogant,' and, giving the sentence\n    a moralizing tone, renders substantially as in the body of this work.\n    (Cf. 28_13 et seq.)\n\n    [2] The passage beginning here is very much disputed. 'The bill of the\n    old lord' is by some regarded as Beowulf's sword; by others, as that\n    of the ancient possessor of the hoard. '�r gesc�d' (2778), translated\n    in this work as verb and adverb, is by some regarded as a compound\n    participial adj. = _sheathed in brass_.\n\n\n\n\nXXXIX.\n\nTHE DEAD FOES.--WIGLAF'S BITTER TAUNTS.\n\n\n{Wiglaf is sorely grieved to see his lord look so un-warlike.}\n\n          It had wofully chanced then the youthful retainer\n          To behold on earth the most ardent-belov�d\n          At his life-days' limit, lying there helpless.\n          The slayer too lay there, of life all bereav�d,\n        5 Horrible earth-drake, harassed with sorrow:\n\n{The dragon has plundered his last hoard.}\n\n          The round-twisted monster was permitted no longer\n          To govern the ring-hoards, but edges of war-swords\n          Mightily seized him, battle-sharp, sturdy\n          Leavings of hammers, that still from his wounds\n       10 The flier-from-farland fell to the earth\n          Hard by his hoard-house, hopped he at midnight\n          Not e'er through the air, nor exulting in jewels\n          Suffered them to see him: but he sank then to earthward\n          Through the hero-chief's handwork. I heard sure it throve then\n\n[96]\n\n{Few warriors dared to face the monster.}\n\n       15 But few in the land of liegemen of valor,\n          Though of every achievement bold he had proved him,\n          To run 'gainst the breath of the venomous scather,\n          Or the hall of the treasure to trouble with hand-blows,\n          If he watching had found the ward of the hoard-hall\n       20 On the barrow abiding. Beowulf's part of\n          The treasure of jewels was paid for with death;\n          Each of the twain had attained to the end of\n          Life so unlasting. Not long was the time till\n\n{The cowardly thanes come out of the thicket.}\n\n          The tardy-at-battle returned from the thicket,\n       25 The timid truce-breakers ten all together,\n          Who durst not before play with the lances\n          In the prince of the people's pressing emergency;\n\n{They are ashamed of their desertion.}\n\n          But blushing with shame, with shields they betook them,\n          With arms and armor where the old one was lying:\n       30 They gazed upon Wiglaf. He was sitting exhausted,\n          Foot-going fighter, not far from the shoulders\n          Of the lord of the people, would rouse him with water;\n          No whit did it help him; though he hoped for it keenly,\n          He was able on earth not at all in the leader\n       35 Life to retain, and nowise to alter\n          The will of the Wielder; the World-Ruler's power[1]\n          Would govern the actions of each one of heroes,\n\n{Wiglaf is ready to excoriate them.}\n\n          As yet He is doing. From the young one forthwith then\n          Could grim-worded greeting be got for him quickly\n       40 Whose courage had failed him. Wiglaf discoursed then,\n          Weohstan his son, sad-mooded hero,\n\n{He begins to taunt them.}\n\n          Looked on the hated: \"He who soothness will utter\n          Can say that the liegelord who gave you the jewels,\n          The ornament-armor wherein ye are standing,\n       45 When on ale-bench often he offered to hall-men\n          Helmet and burnie, the prince to his liegemen,\n          As best upon earth he was able to find him,--\n\n[97]\n\n{Surely our lord wasted his armor on poltroons.}\n\n          That he wildly wasted his war-gear undoubtedly\n          When battle o'ertook him.[2] The troop-king no need had\n       50 To glory in comrades; yet God permitted him,\n\n{He, however, got along without you}\n\n          Victory-Wielder, with weapon unaided\n          Himself to avenge, when vigor was needed.\n          I life-protection but little was able\n          To give him in battle, and I 'gan, notwithstanding,\n\n{With some aid, I could have saved our liegelord}\n\n       55 Helping my kinsman (my strength overtaxing):\n          He waxed the weaker when with weapon I smote on\n          My mortal opponent, the fire less strongly\n          Flamed from his bosom. Too few of protectors\n          Came round the king at the critical moment.\n\n{Gift-giving is over with your people: the ring-lord is dead.}\n\n       60 Now must ornament-taking and weapon-bestowing,\n          Home-joyance all, cease for your kindred,\n          Food for the people; each of your warriors\n          Must needs be bereav�d of rights that he holdeth\n          In landed possessions, when faraway nobles\n       65 Shall learn of your leaving your lord so basely,\n\n{What is life without honor?}\n\n          The dastardly deed. Death is more pleasant\n          To every earlman than infamous life is!\"\n\n    [1] For 'd�dum r�dan' (2859) B. suggests 'd�a� �r�dan,' and renders:\n    _The might (or judgment) of God would determine death for every man,\n    as he still does._\n\n    [2] Some critics, H. himself in earlier editions, put the clause,\n    'When ... him' (A.-S. '�� ... beget') with the following sentence;\n    that is, they make it dependent upon '�orfte' (2875) instead of upon\n    'forwurpe' (2873).\n\n\n\n\nXL.\n\nTHE MESSENGER OF DEATH.\n\n\n{Wiglaf sends the news of Beowulf's death to liegemen near by.}\n\n          Then he charged that the battle be announced at the hedge\n          Up o'er the cliff-edge, where the earl-troopers bided\n          The whole of the morning, mood-wretched sat them,\n          Bearers of battle-shields, both things expecting,\n        5 The end of his lifetime and the coming again of\n          The liegelord belov�d. Little reserved he\n          Of news that was known, who the ness-cliff did travel,\n          But he truly discoursed to all that could hear him:\n\n[98]\n\n{The messenger speaks.}\n\n          \"Now the free-giving friend-lord of the folk of the Weders,\n       10 The folk-prince of Geatmen, is fast in his death-bed,\n          By the deeds of the dragon in death-bed abideth;\n          Along with him lieth his life-taking foeman\n          Slain with knife-wounds: he was wholly unable\n          To injure at all the ill-planning monster\n\n{Wiglaf sits by our dead lord.}\n\n       15 With bite of his sword-edge. Wiglaf is sitting,\n          Offspring of Wihstan, up over Beowulf,\n          Earl o'er another whose end-day hath reached him,\n          Head-watch holdeth o'er heroes unliving,[1]\n\n{Our lord's death will lead to attacks from our old foes.}\n\n          For friend and for foeman. The folk now expecteth\n       20 A season of strife when the death of the folk-king\n          To Frankmen and Frisians in far-lands is published.\n          The war-hatred waxed warm 'gainst the Hugmen,\n\n{Higelac's death recalled.}\n\n          When Higelac came with an army of vessels\n          Faring to Friesland, where the Frankmen in battle\n       25 Humbled him and bravely with overmight 'complished\n          That the mail-clad warrior must sink in the battle,\n          Fell 'mid his folk-troop: no fret-gems presented\n          The atheling to earlmen; aye was denied us\n          Merewing's mercy. The men of the Swedelands\n       30 For truce or for truth trust I but little;\n          But widely 'twas known that near Ravenswood Ongentheow\n\n{H�thcyn's fall referred to.}\n\n          Sundered H�thcyn the Hrethling from life-joys,\n          When for pride overweening the War-Scylfings first did\n          Seek the Geatmen with savage intentions.\n       35 Early did Ohthere's age-laden father,\n          Old and terrible, give blow in requital,\n          Killing the sea-king, the queen-mother rescued,\n          The old one his consort deprived of her gold,\n          Onela's mother and Ohthere's also,\n[99]   40 And then followed the feud-nursing foemen till hardly,\n          Reaved of their ruler, they Ravenswood entered.\n          Then with vast-numbered forces he assaulted the remnant,\n          Weary with wounds, woe often promised\n          The livelong night to the sad-hearted war-troop:\n       45 Said he at morning would kill them with edges of weapons,\n          Some on the gallows for glee to the fowls.\n          Aid came after to the anxious-in-spirit\n          At dawn of the day, after Higelac's bugle\n          And trumpet-sound heard they, when the good one proceeded\n       50 And faring followed the flower of the troopers.\n\n    [1] 'Hige-m��um' (2910) is glossed by H. as dat. plu. (= for the\n    dead). S. proposes 'hige-m��e,' nom. sing. limiting Wigl�f; i.e. _W.,\n    mood-weary, holds head-watch o'er friend and foe_.--B. suggests taking\n    the word as dat. inst. plu. of an abstract noun in -'u.' The\n    translation would be substantially the same as S.'s.\n\n\n\n\nXLI.\n\nTHE MESSENGER'S RETROSPECT.\n\n\n{The messenger continues, and refers to the feuds of Swedes and Geats.}\n\n          \"The blood-stain�d trace of Swedes and Geatmen,\n          The death-rush of warmen, widely was noticed,\n          How the folks with each other feud did awaken.\n          The worthy one went then[1] with well-beloved comrades,\n        5 Old and dejected to go to the fastness,\n          Ongentheo earl upward then turned him;\n          Of Higelac's battle he'd heard on inquiry,\n          The exultant one's prowess, despaired of resistance,\n          With earls of the ocean to be able to struggle,\n       10 'Gainst sea-going sailors to save the hoard-treasure,\n          His wife and his children; he fled after thenceward\n          Old 'neath the earth-wall. Then was offered pursuance\n          To the braves of the Swedemen, the banner[2] to Higelac.\n[100]     They fared then forth o'er the field-of-protection,\n       15 When the Hrethling heroes hedgeward had thronged them.\n          Then with edges of irons was Ongentheow driven,\n          The gray-haired to tarry, that the troop-ruler had to\n          Suffer the power solely of Eofor:\n\n{Wulf wounds Ongentheow.}\n\n          Wulf then wildly with weapon assaulted him,\n       20 Wonred his son, that for swinge of the edges\n          The blood from his body burst out in currents,\n          Forth 'neath his hair. He feared not however,\n          Gray-headed Scylfing, but speedily quited\n\n{Ongentheow gives a stout blow in return.}\n\n          The wasting wound-stroke with worse exchange,\n       25 When the king of the thane-troop thither did turn him:\n          The wise-mooded son of Wonred was powerless\n          To give a return-blow to the age-hoary man,\n          But his head-shielding helmet first hewed he to pieces,\n          That flecked with gore perforce he did totter,\n       30 Fell to the earth; not fey was he yet then,\n          But up did he spring though an edge-wound had reached him.\n\n{Eofor smites Ongentheow fiercely.}\n\n          Then Higelac's vassal, valiant and dauntless,\n          When his brother lay dead, made his broad-bladed weapon,\n          Giant-sword ancient, defence of the giants,\n       35 Bound o'er the shield-wall; the folk-prince succumbed then,\n\n{Ongentheow is slain.}\n\n          Shepherd of people, was pierced to the vitals.\n          There were many attendants who bound up his kinsman,\n          Carried him quickly when occasion was granted\n          That the place of the slain they were suffered to manage.\n       40 This pending, one hero plundered the other,\n          His armor of iron from Ongentheow ravished,\n          His hard-sword hilted and helmet together;\n\n{Eofor takes the old king's war-gear to Higelac.}\n\n          The old one's equipments he carried to Higelac.\n          He the jewels received, and rewards 'mid the troopers\n       45 Graciously promised, and so did accomplish:\n          The king of the Weders requited the war-rush,\n          Hrethel's descendant, when home he repaired him,\n\n{Higelac rewards the brothers.}\n\n          To Eofor and Wulf with wide-lavished treasures,\n          To each of them granted a hundred of thousands\n[101]  50 In land and rings wrought out of wire:\n\n{His gifts were beyond cavil.}\n\n          None upon mid-earth needed to twit him[3]\n          With the gifts he gave them, when glory they conquered;\n\n{To Eofor he also gives his only daughter in marriage.}\n\n          And to Eofor then gave he his one only daughter,\n          The honor of home, as an earnest of favor.\n       55 That's the feud and hatred--as ween I 'twill happen--\n          The anger of earthmen, that earls of the Swedemen\n          Will visit on us, when they hear that our leader\n          Lifeless is lying, he who longtime protected\n          His hoard and kingdom 'gainst hating assailers,\n       60 Who on the fall of the heroes defended of yore\n          The deed-mighty Scyldings,[4] did for the troopers\n          What best did avail them, and further moreover\n\n{It is time for us to pay the last marks of respect to our lord.}\n\n          Hero-deeds 'complished. Now is haste most fitting,\n          That the lord of liegemen we look upon yonder,\n       65 And _that_ one carry on journey to death-pyre\n          Who ring-presents gave us. Not aught of it all\n          Shall melt with the brave one--there's a mass of bright jewels,\n          Gold beyond measure, grewsomely purchased\n          And ending it all ornament-rings too\n       70 Bought with his life; these fire shall devour,\n          Flame shall cover, no earlman shall wear\n          A jewel-memento, nor beautiful virgin\n          Have on her neck rings to adorn her,\n          But wretched in spirit bereav�d of gold-gems\n       75 She shall oft with others be exiled and banished,\n          Since the leader of liegemen hath laughter forsaken,\n[102]     Mirth and merriment. Hence many a war-spear\n          Cold from the morning shall be clutched in the fingers,\n          Heaved in the hand, no harp-music's sound shall\n       80 Waken the warriors, but the wan-coated raven\n          Fain over fey ones freely shall gabble,\n          Shall say to the eagle how he sped in the eating,\n          When, the wolf his companion, he plundered the slain.\"\n          So the high-minded hero was rehearsing these stories\n       85 Loathsome to hear; he lied as to few of\n\n{The warriors go sadly to look at Beowulf's lifeless body.}\n\n          Weirds and of words. All the war-troop arose then,\n          'Neath the Eagle's Cape sadly betook them,\n          Weeping and woful, the wonder to look at.\n          They saw on the sand then soulless a-lying,\n       90 His slaughter-bed holding, him who rings had given them\n          In days that were done; then the death-bringing moment\n          Was come to the good one, that the king very warlike,\n          Wielder of Weders, with wonder-death perished.\n          First they beheld there a creature more wondrous,\n\n{They also see the dragon.}\n\n       95 The worm on the field, in front of them lying,\n          The foeman before them: the fire-spewing dragon,\n          Ghostly and grisly guest in his terrors,\n          Was scorched in the fire; as he lay there he measured\n          Fifty of feet; came forth in the night-time[5]\n      100 To rejoice in the air, thereafter departing\n          To visit his den; he in death was then fastened,\n          He would joy in no other earth-hollowed caverns.\n          There stood round about him beakers and vessels,\n          Dishes were lying and dear-valued weapons,\n      105 With iron-rust eaten, as in earth's mighty bosom\n          A thousand of winters there they had rested:\n\n{The hoard was under a magic spell.}\n\n          That mighty bequest then with magic was guarded,\n          Gold of the ancients, that earlman not any\n          The ring-hall could touch, save Ruling-God only,\n[103] 110 Sooth-king of Vict'ries gave whom He wished to\n\n{God alone could give access to it.}\n\n          [6](He is earth-folk's protector) to open the treasure,\n          E'en to such among mortals as seemed to Him proper.\n\n    [1] For 'g�da,' which seems a surprising epithet for a Geat to apply\n    to the \"terrible\" Ongentheow, B. suggests 'gomela.' The passage would\n    then stand: '_The old one went then,' etc._\n\n    [2] For 'segn Higel�ce,' K., Th., and B. propose 'segn Higel�ces,'\n    meaning: _Higelac's banner followed the Swedes (in pursuit)._--S.\n    suggests 's�cc Higel�ces,' and renders: _Higelac's pursuit._--The\n    H.-So. reading, as translated in our text, means that the banner of\n    the enemy was captured and brought to Higelac as a trophy.\n\n    [3] The rendering given in this translation represents the king as\n    being generous beyond the possibility of reproach; but some\n    authorities construe 'him' (2996) as plu., and understand the passage\n    to mean that no one reproached the two brothers with having received\n    more reward than they were entitled to.\n\n    [4] The name 'Scyldingas' here (3006) has caused much discussion, and\n    given rise to several theories, the most important of which are as\n    follows: (1) After the downfall of Hrothgar's family, Beowulf was king\n    of the Danes, or Scyldings. (2) For 'Scyldingas' read\n    'Scylfingas'--that is, after killing Eadgils, the Scylfing prince,\n    Beowulf conquered his land, and held it in subjection. (3) M.\n    considers 3006 a thoughtless repetition of 2053. (Cf. H.-So.)\n\n    [5] B. takes 'nihtes' and 'hw�lum' (3045) as separate adverbial cases,\n    and renders: _Joy in the air had he of yore by night, etc_. He thinks\n    that the idea of vanished time ought to be expressed.\n\n    [6] The parenthesis is by some emended so as to read: (1) (_He_ (i.e.\n    _God_) _is the hope of men_); (2) (_he is the hope of heroes_). Gr.'s\n    reading has no parenthesis, but says: ... _could touch, unless God\n    himself, true king of victories, gave to whom he would to open the\n    treasure, the secret place of enchanters, etc_. The last is rejected\n    on many grounds.\n\n\n\n\nXLII.\n\nWIGLAF'S SAD STORY.--THE HOARD CARRIED OFF.\n\n\n          Then 'twas seen that the journey prospered him little\n          Who wrongly within had the ornaments hidden[1]\n          Down 'neath the wall. The warden erst slaughtered\n          Some few of the folk-troop: the feud then thereafter\n        5 Was hotly aveng�d. 'Tis a wonder where,[2]\n          When the strength-famous trooper has attained to the end of\n          Life-days allotted, then no longer the man may\n          Remain with his kinsmen where mead-cups are flowing.\n          So to Beowulf happened when the ward of the barrow,\n       10 Assaults, he sought for: himself had no knowledge\n          How his leaving this life was likely to happen.\n          So to doomsday, famous folk-leaders down did\n          Call it with curses--who 'complished it there--\n[104]     That that man should be ever of ill-deeds convicted,\n       15 Confined in foul-places, fastened in hell-bonds,\n          Punished with plagues, who this place should e'er ravage.[3]\n          He cared not for gold: rather the Wielder's\n          Favor preferred he first to get sight of.[4]\n\n{Wiglaf addresses his comrades.}\n\n          Wiglaf discoursed then, Wihstan his son:\n       20 \"Oft many an earlman on one man's account must\n          Sorrow endure, as to us it hath happened.\n          The liegelord belov�d we could little prevail on,\n          Kingdom's keeper, counsel to follow,\n          Not to go to the guardian of the gold-hoard, but let him\n       25 Lie where he long was, live in his dwelling\n          Till the end of the world. Met we a destiny\n          Hard to endure: the hoard has been looked at,\n          Been gained very grimly; too grievous the fate that[5]\n          The prince of the people pricked to come thither.\n       30 _I_ was therein and all of it looked at,\n          The building's equipments, since access was given me,\n          Not kindly at all entrance permitted\n\n{He tells them of Beowulf's last moments.}\n\n          Within under earth-wall. Hastily seized I\n          And held in my hands a huge-weighing burden\n       35 Of hoard-treasures costly, hither out bare them\n          To my liegelord belov�d: life was yet in him,\n          And consciousness also; the old one discoursed then\n          Much and mournfully, commanded to greet you,\n\n{Beowulf's dying request.}\n\n          Bade that remembering the deeds of your friend-lord\n       40 Ye build on the fire-hill of corpses a lofty\n          Burial-barrow, broad and far-famous,\n          As 'mid world-dwelling warriors he was widely most honored\n          While he reveled in riches. Let us rouse us and hasten\n[105]     Again to see and seek for the treasure,\n       45 The wonder 'neath wall. The way I will show you,\n          That close ye may look at ring-gems sufficient\n          And gold in abundance. Let the bier with promptness\n          Fully be fashioned, when forth we shall come,\n          And lift we our lord, then, where long he shall tarry,\n       50 Well-beloved warrior, 'neath the Wielder's protection.\"\n\n{Wiglaf charges them to build a funeral-pyre.}\n\n          Then the son of Wihstan bade orders be given,\n          Mood-valiant man, to many of heroes,\n          Holders of homesteads, that they hither from far,\n          [6]Leaders of liegemen, should look for the good one\n       55 With wood for his pyre: \"The flame shall now swallow\n          (The wan fire shall wax[7]) the warriors' leader\n          Who the rain of the iron often abided,\n          When, sturdily hurled, the storm of the arrows\n          Leapt o'er linden-wall, the lance rendered service,\n       60 Furnished with feathers followed the arrow.\"\n          Now the wise-mooded son of Wihstan did summon\n          The best of the braves from the band of the ruler\n\n{He takes seven thanes, and enters the den.}\n\n          Seven together; 'neath the enemy's roof he\n          Went with the seven; one of the heroes\n       65 Who fared at the front, a fire-blazing torch-light\n          Bare in his hand. No lot then decided\n          Who that hoard should havoc, when hero-earls saw it\n          Lying in the cavern uncared-for entirely,\n          Rusting to ruin: they rued then but little\n       70 That they hastily hence hauled out the treasure,\n\n{They push the dragon over the wall.}\n\n          The dear-valued jewels; the dragon eke pushed they,\n          The worm o'er the wall, let the wave-currents take him,\n[106]     The waters enwind the ward of the treasures.\n\n{The hoard is laid on a wain.}\n\n          There wounden gold on a wain was uploaded,\n       75 A mass unmeasured, the men-leader off then,\n          The hero hoary, to Whale's-Ness was carried.\n\n    [1] For 'geh�dde,' B. suggests 'geh��de': the passage would stand as\n    above except the change of 'hidden' (v. 2) to 'plundered.' The\n    reference, however, would be to the thief, not to the dragon.\n\n    [2] The passage 'Wundur ... b�an' (3063-3066), M. took to be a\n    question asking whether it was strange that a man should die when his\n    appointed time had come.--B. sees a corruption, and makes emendations\n    introducing the idea that a brave man should not die from sickness or\n    from old age, but should find death in the performance of some deed of\n    daring.--S. sees an indirect question introduced by 'hw�r' and\n    dependent upon 'wundur': _A secret is it when the hero is to die,\n    etc_.--Why may the two clauses not be parallel, and the whole passage\n    an Old English cry of '_How wonderful is death!'?_--S.'s is the best\n    yet offered, if 'wundor' means 'mystery.'\n\n    [3] For 'strude' in H.-So., S. suggests 'stride.' This would require\n    'ravage' (v. 16) to be changed to 'tread.'\n\n    [4] 'He cared ... sight of' (17, 18), S. emends so as to read as\n    follows: _He (Beowulf) had not before seen the favor of the avaricious\n    possessor._\n\n    [5] B. renders: _That which drew the king thither_ (i.e. _the\n    treasure_) _was granted us, but in such a way that it overcomes us._\n\n    [6] 'Folc-�gende' (3114) B. takes as dat. sing. with 'g�dum,' and\n    refers it to Beowulf; that is, _Should bring fire-wood to the place\n    where the good folk-ruler lay_.\n\n    [7] C. proposes to take 'weaxan' = L. 'vescor,' and translate\n    _devour_. This gives a parallel to 'fretan' above. The parenthesis\n    would be discarded and the passage read: _Now shall the fire consume,\n    the wan-flame devour, the prince of warriors, etc_.\n\n\n\n\nXLIII.\n\nTHE BURNING OF BEOWULF.\n\n\n{Beowulf's pyre.}\n\n          The folk of the Geatmen got him then ready\n          A pile on the earth strong for the burning,\n          Behung with helmets, hero-knights' targets,\n          And bright-shining burnies, as he begged they should have them;\n        5 Then wailing war-heroes their world-famous chieftain,\n          Their liegelord beloved, laid in the middle.\n\n{The funeral-flame.}\n\n          Soldiers began then to make on the barrow\n          The largest of dead-fires: dark o'er the vapor\n          The smoke-cloud ascended, the sad-roaring fire,\n       10 Mingled with weeping (the wind-roar subsided)\n          Till the building of bone it had broken to pieces,\n          Hot in the heart. Heavy in spirit\n          They mood-sad lamented the men-leader's ruin;\n          And mournful measures the much-grieving widow\n       15 *�������*�������*�������*�������*�������*�������*\n          *�������*�������*�������*�������*�������*�������*\n          *�������*�������*�������*�������*�������*�������*\n          *�������*�������*�������*�������*�������*�������*\n          *�������*�������*�������*�������*�������*�������*\n       20 *�������*�������*�������*�������*�������*�������*\n\n{The Weders carry out their lord's last request.}\n\n          The men of the Weders made accordingly\n          A hill on the height, high and extensive,\n          Of sea-going sailors to be seen from a distance,\n          And the brave one's beacon built where the fire was,\n       25 In ten-days' space, with a wall surrounded it,\n          As wisest of world-folk could most worthily plan it.\n          They placed in the barrow rings and jewels,\n\n[107]\n\n{Rings and gems are laid in the barrow.}\n\n          All such ornaments as erst in the treasure\n          War-mooded men had won in possession:\n       30 The earnings of earlmen to earth they entrusted,\n          The gold to the dust, where yet it remaineth\n          As useless to mortals as in foregoing eras.\n          'Round the dead-mound rode then the doughty-in-battle,\n          Bairns of all twelve of the chiefs of the people,\n\n{They mourn for their lord, and sing his praises.}\n\n       35 More would they mourn, lament for their ruler,\n          Speak in measure, mention him with pleasure,\n          Weighed his worth, and his warlike achievements\n          Mightily commended, as 'tis meet one praise his\n          Liegelord in words and love him in spirit,\n       40 When forth from his body he fares to destruction.\n          So lamented mourning the men of the Geats,\n          Fond-loving vassals, the fall of their lord,\n\n{An ideal king.}\n\n          Said he was kindest of kings under heaven,\n          Gentlest of men, most winning of manner,\n       45 Friendliest to folk-troops and fondest of honor.\n\n[109]\n\n\n\n\nADDENDA.\n\n\nSeveral discrepancies and other oversights have been noticed in the H.-So.\nglossary. Of these a good part were avoided by Harrison and Sharp, the\nAmerican editors of Beowulf, in their last edition, 1888. The rest will, I\nhope, be noticed in their fourth edition. As, however, this book may fall\ninto the hands of some who have no copy of the American edition, it seems\nbest to notice all the principal oversights of the German editors.\n\n~From h�m~ (194).--Notes and glossary conflict; the latter not having been\naltered to suit the conclusions accepted in the former.\n\n~��r gel�fan sceal dryhtnes d�me~ (440).--Under 'd�m' H. says 'the might\nof the Lord'; while under 'gel�fan' he says 'the judgment of the Lord.'\n\n~Eal benc�elu~ (486).--Under 'benc-�elu' H. says _nom. plu._; while under\n'eal' he says _nom. sing._\n\n~Heatho-r�mas~ (519).--Under '�tberan' H. translates 'to the Heathoremes';\nwhile under 'Heatho-r�mas' he says 'Heathor�mas reaches Breca in the\nswimming-match with Beowulf.' Harrison and Sharp (3d edition, 1888) avoid\nthe discrepancy.\n\n~F�h f�ond-sca�a~ (554).--Under 'f�ond-sca�a' H. says 'a gleaming\nsea-monster'; under 'f�h' he says 'hostile.'\n\n~Onfeng hra�e inwit-�ancum~ (749).--Under 'onf�n' H. says 'he _received_\nthe maliciously-disposed one'; under 'inwit-�anc' he says 'he _grasped_,'\netc.\n\n~N��-wundor s�on~ (1366).--Under 'n��-wundor' H. calls this word itself\n_nom. sing._; under 's�on' he translates it as accus. sing., understanding\n'man' as subject of 's�on.' H. and S. (3d edition) make the correction.\n\n~Forgeaf hilde-bille~ (1521).--H., under the second word, calls it instr.\ndat.; while under 'forgifan' he makes it the dat. of indir. obj. H. and S.\n(3d edition) make the change.\n\n~Br�d~ and ~br�n-ecg~ (1547).--Under 'br�d' H. says 'das breite H�ftmesser\nmit bronzener Klinge'; under 'br�n-ecg' he says 'ihr breites H�ftmesser\nmit blitzender Klinge.'\n\n[110]\n\n~Y�el�ce~ (1557).--Under this word H. makes it modify '�st�d.' If this be\nright, the punctuation of the fifth edition is wrong. See H. and S.,\nappendix.\n\n~S�lran ges�hte~ (1840).--Under 's�l' and 'ges�can' H. calls these two\nwords accus. plu.; but this is clearly an error, as both are nom. plu.,\npred. nom. H. and S. correct under 's�l.'\n\n~Wi� sylfne~ (1978).--Under 'wi�' and 'gesittan' H. says 'wi� = near, by';\nunder 'self' he says 'opposite.'\n\n~��ow~ (2225) is omitted from the glossary.\n\n~For dugu�um~ (2502).--Under 'dugu�' H. translates this phrase, 'in\nT�chtigkeit'; under 'for,' by 'vor der edlen Kriegerschaar.'\n\n~��r~ (2574).--Under 'wealdan' H. translates _��r_ by 'wo'; under 'm�tan,'\nby 'da.' H. and S. suggest 'if' in both passages.\n\n~Wunde~ (2726).--Under 'wund' H. says 'dative,' and under 'w�l-bl�ate' he\nsays 'accus.' It is without doubt accus., parallel with 'benne.'\n\n~Strengum geb�ded~ (3118).--Under 'strengo' H. says 'Strengum' = mit\nMacht; under 'geb�ded' he translates 'von den Sehnen.' H. and S. correct\nthis discrepancy by rejecting the second reading.\n\n~Bronda be l�fe~ (3162).--A recent emendation. The fourth edition had\n'bronda betost.' In the fifth edition the editor neglects to change the\nglossary to suit the new emendation. See 'bewyrcan.'\n\n\n\n\n\nEnd of the Project Gutenberg EBook of Beowulf\n\n*** END OF THIS PROJECT GUTENBERG EBOOK BEOWULF ***\n\n***** This file should be named 16328-8.txt or 16328-8.zip *****\nThis and all associated files of various formats will be found in:\n        http://www.gutenberg.org/1/6/3/2/16328/\n\nProduced by David Starner, Dainis Millers and the Online\nDistributed Proofreading Team at http://www.pgdp.net\n\n\nUpdated editions will replace the previous one--the old editions\nwill be renamed.\n\nCreating the works from public domain print editions means that no\none owns a United States copyright in these works, so the Foundation\n(and you!) can copy and distribute it in the United States without\npermission and without paying copyright royalties.  Special rules,\nset forth in the General Terms of Use part of this license, apply to\ncopying and distributing Project Gutenberg-tm electronic works to\nprotect the PROJECT GUTENBERG-tm concept and trademark.  Project\nGutenberg is a registered trademark, and may not be used if you\ncharge for the eBooks, unless you receive specific permission.  If you\ndo not charge anything for copies of this eBook, complying with the\nrules is very easy.  You may use this eBook for nearly any purpose\nsuch as creation of derivative works, reports, performances and\nresearch.  They may be modified and printed and given away--you may do\npractically ANYTHING with public domain eBooks.  Redistribution is\nsubject to the trademark license, especially commercial\nredistribution.\n\n\n\n*** START: FULL LICENSE ***\n\nTHE FULL PROJECT GUTENBERG LICENSE\nPLEASE READ THIS BEFORE YOU DISTRIBUTE OR USE THIS WORK\n\nTo protect the Project Gutenberg-tm mission of promoting the free\ndistribution of electronic works, by using or distributing this work\n(or any other work associated in any way with the phrase \"Project\nGutenberg\"), you agree to comply with all the terms of the Full Project\nGutenberg-tm License (available with this file or online at\nhttp://gutenberg.net/license).\n\n\nSection 1.  General Terms of Use and Redistributing Project Gutenberg-tm\nelectronic works\n\n1.A.  By reading or using any part of this Project Gutenberg-tm\nelectronic work, you indicate that you have read, understand, agree to\nand accept all the terms of this license and intellectual property\n(trademark/copyright) agreement.  If you do not agree to abide by all\nthe terms of this agreement, you must cease using and return or destroy\nall copies of Project Gutenberg-tm electronic works in your possession.\nIf you paid a fee for obtaining a copy of or access to a Project\nGutenberg-tm electronic work and you do not agree to be bound by the\nterms of this agreement, you may obtain a refund from the person or\nentity to whom you paid the fee as set forth in paragraph 1.E.8.\n\n1.B.  \"Project Gutenberg\" is a registered trademark.  It may only be\nused on or associated in any way with an electronic work by people who\nagree to be bound by the terms of this agreement.  There are a few\nthings that you can do with most Project Gutenberg-tm electronic works\neven without complying with the full terms of this agreement.  See\nparagraph 1.C below.  There are a lot of things you can do with Project\nGutenberg-tm electronic works if you follow the terms of this agreement\nand help preserve free future access to Project Gutenberg-tm electronic\nworks.  See paragraph 1.E below.\n\n1.C.  The Project Gutenberg Literary Archive Foundation (\"the Foundation\"\nor PGLAF), owns a compilation copyright in the collection of Project\nGutenberg-tm electronic works.  Nearly all the individual works in the\ncollection are in the public domain in the United States.  If an\nindividual work is in the public domain in the United States and you are\nlocated in the United States, we do not claim a right to prevent you from\ncopying, distributing, performing, displaying or creating derivative\nworks based on the work as long as all references to Project Gutenberg\nare removed.  Of course, we hope that you will support the Project\nGutenberg-tm mission of promoting free access to electronic works by\nfreely sharing Project Gutenberg-tm works in compliance with the terms of\nthis agreement for keeping the Project Gutenberg-tm name associated with\nthe work.  You can easily comply with the terms of this agreement by\nkeeping this work in the same format with its attached full Project\nGutenberg-tm License when you share it without charge with others.\n\n1.D.  The copyright laws of the place where you are located also govern\nwhat you can do with this work.  Copyright laws in most countries are in\na constant state of change.  If you are outside the United States, check\nthe laws of your country in addition to the terms of this agreement\nbefore downloading, copying, displaying, performing, distributing or\ncreating derivative works based on this work or any other Project\nGutenberg-tm work.  The Foundation makes no representations concerning\nthe copyright status of any work in any country outside the United\nStates.\n\n1.E.  Unless you have removed all references to Project Gutenberg:\n\n1.E.1.  The following sentence, with active links to, or other immediate\naccess to, the full Project Gutenberg-tm License must appear prominently\nwhenever any copy of a Project Gutenberg-tm work (any work on which the\nphrase \"Project Gutenberg\" appears, or with which the phrase \"Project\nGutenberg\" is associated) is accessed, displayed, performed, viewed,\ncopied or distributed:\n\nThis eBook is for the use of anyone anywhere at no cost and with\nalmost no restrictions whatsoever.  You may copy it, give it away or\nre-use it under the terms of the Project Gutenberg License included\nwith this eBook or online at www.gutenberg.net\n\n1.E.2.  If an individual Project Gutenberg-tm electronic work is derived\nfrom the public domain (does not contain a notice indicating that it is\nposted with permission of the copyright holder), the work can be copied\nand distributed to anyone in the United States without paying any fees\nor charges.  If you are redistributing or providing access to a work\nwith the phrase \"Project Gutenberg\" associated with or appearing on the\nwork, you must comply either with the requirements of paragraphs 1.E.1\nthrough 1.E.7 or obtain permission for the use of the work and the\nProject Gutenberg-tm trademark as set forth in paragraphs 1.E.8 or\n1.E.9.\n\n1.E.3.  If an individual Project Gutenberg-tm electronic work is posted\nwith the permission of the copyright holder, your use and distribution\nmust comply with both paragraphs 1.E.1 through 1.E.7 and any additional\nterms imposed by the copyright holder.  Additional terms will be linked\nto the Project Gutenberg-tm License for all works posted with the\npermission of the copyright holder found at the beginning of this work.\n\n1.E.4.  Do not unlink or detach or remove the full Project Gutenberg-tm\nLicense terms from this work, or any files containing a part of this\nwork or any other work associated with Project Gutenberg-tm.\n\n1.E.5.  Do not copy, display, perform, distribute or redistribute this\nelectronic work, or any part of this electronic work, without\nprominently displaying the sentence set forth in paragraph 1.E.1 with\nactive links or immediate access to the full terms of the Project\nGutenberg-tm License.\n\n1.E.6.  You may convert to and distribute this work in any binary,\ncompressed, marked up, nonproprietary or proprietary form, including any\nword processing or hypertext form.  However, if you provide access to or\ndistribute copies of a Project Gutenberg-tm work in a format other than\n\"Plain Vanilla ASCII\" or other format used in the official version\nposted on the official Project Gutenberg-tm web site (www.gutenberg.net),\nyou must, at no additional cost, fee or expense to the user, provide a\ncopy, a means of exporting a copy, or a means of obtaining a copy upon\nrequest, of the work in its original \"Plain Vanilla ASCII\" or other\nform.  Any alternate format must include the full Project Gutenberg-tm\nLicense as specified in paragraph 1.E.1.\n\n1.E.7.  Do not charge a fee for access to, viewing, displaying,\nperforming, copying or distributing any Project Gutenberg-tm works\nunless you comply with paragraph 1.E.8 or 1.E.9.\n\n1.E.8.  You may charge a reasonable fee for copies of or providing\naccess to or distributing Project Gutenberg-tm electronic works provided\nthat\n\n- You pay a royalty fee of 20% of the gross profits you derive from\n     the use of Project Gutenberg-tm works calculated using the method\n     you already use to calculate your applicable taxes.  The fee is\n     owed to the owner of the Project Gutenberg-tm trademark, but he\n     has agreed to donate royalties under this paragraph to the\n     Project Gutenberg Literary Archive Foundation.  Royalty payments\n     must be paid within 60 days following each date on which you\n     prepare (or are legally required to prepare) your periodic tax\n     returns.  Royalty payments should be clearly marked as such and\n     sent to the Project Gutenberg Literary Archive Foundation at the\n     address specified in Section 4, \"Information about donations to\n     the Project Gutenberg Literary Archive Foundation.\"\n\n- You provide a full refund of any money paid by a user who notifies\n     you in writing (or by e-mail) within 30 days of receipt that s/he\n     does not agree to the terms of the full Project Gutenberg-tm\n     License.  You must require such a user to return or\n     destroy all copies of the works possessed in a physical medium\n     and discontinue all use of and all access to other copies of\n     Project Gutenberg-tm works.\n\n- You provide, in accordance with paragraph 1.F.3, a full refund of any\n     money paid for a work or a replacement copy, if a defect in the\n     electronic work is discovered and reported to you within 90 days\n     of receipt of the work.\n\n- You comply with all other terms of this agreement for free\n     distribution of Project Gutenberg-tm works.\n\n1.E.9.  If you wish to charge a fee or distribute a Project Gutenberg-tm\nelectronic work or group of works on different terms than are set\nforth in this agreement, you must obtain permission in writing from\nboth the Project Gutenberg Literary Archive Foundation and Michael\nHart, the owner of the Project Gutenberg-tm trademark.  Contact the\nFoundation as set forth in Section 3 below.\n\n1.F.\n\n1.F.1.  Project Gutenberg volunteers and employees expend considerable\neffort to identify, do copyright research on, transcribe and proofread\npublic domain works in creating the Project Gutenberg-tm\ncollection.  Despite these efforts, Project Gutenberg-tm electronic\nworks, and the medium on which they may be stored, may contain\n\"Defects,\" such as, but not limited to, incomplete, inaccurate or\ncorrupt data, transcription errors, a copyright or other intellectual\nproperty infringement, a defective or damaged disk or other medium, a\ncomputer virus, or computer codes that damage or cannot be read by\nyour equipment.\n\n1.F.2.  LIMITED WARRANTY, DISCLAIMER OF DAMAGES - Except for the \"Right\nof Replacement or Refund\" described in paragraph 1.F.3, the Project\nGutenberg Literary Archive Foundation, the owner of the Project\nGutenberg-tm trademark, and any other party distributing a Project\nGutenberg-tm electronic work under this agreement, disclaim all\nliability to you for damages, costs and expenses, including legal\nfees.  YOU AGREE THAT YOU HAVE NO REMEDIES FOR NEGLIGENCE, STRICT\nLIABILITY, BREACH OF WARRANTY OR BREACH OF CONTRACT EXCEPT THOSE\nPROVIDED IN PARAGRAPH F3.  YOU AGREE THAT THE FOUNDATION, THE\nTRADEMARK OWNER, AND ANY DISTRIBUTOR UNDER THIS AGREEMENT WILL NOT BE\nLIABLE TO YOU FOR ACTUAL, DIRECT, INDIRECT, CONSEQUENTIAL, PUNITIVE OR\nINCIDENTAL DAMAGES EVEN IF YOU GIVE NOTICE OF THE POSSIBILITY OF SUCH\nDAMAGE.\n\n1.F.3.  LIMITED RIGHT OF REPLACEMENT OR REFUND - If you discover a\ndefect in this electronic work within 90 days of receiving it, you can\nreceive a refund of the money (if any) you paid for it by sending a\nwritten explanation to the person you received the work from.  If you\nreceived the work on a physical medium, you must return the medium with\nyour written explanation.  The person or entity that provided you with\nthe defective work may elect to provide a replacement copy in lieu of a\nrefund.  If you received the work electronically, the person or entity\nproviding it to you may choose to give you a second opportunity to\nreceive the work electronically in lieu of a refund.  If the second copy\nis also defective, you may demand a refund in writing without further\nopportunities to fix the problem.\n\n1.F.4.  Except for the limited right of replacement or refund set forth\nin paragraph 1.F.3, this work is provided to you 'AS-IS' WITH NO OTHER\nWARRANTIES OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO\nWARRANTIES OF MERCHANTIBILITY OR FITNESS FOR ANY PURPOSE.\n\n1.F.5.  Some states do not allow disclaimers of certain implied\nwarranties or the exclusion or limitation of certain types of damages.\nIf any disclaimer or limitation set forth in this agreement violates the\nlaw of the state applicable to this agreement, the agreement shall be\ninterpreted to make the maximum disclaimer or limitation permitted by\nthe applicable state law.  The invalidity or unenforceability of any\nprovision of this agreement shall not void the remaining provisions.\n\n1.F.6.  INDEMNITY - You agree to indemnify and hold the Foundation, the\ntrademark owner, any agent or employee of the Foundation, anyone\nproviding copies of Project Gutenberg-tm electronic works in accordance\nwith this agreement, and any volunteers associated with the production,\npromotion and distribution of Project Gutenberg-tm electronic works,\nharmless from all liability, costs and expenses, including legal fees,\nthat arise directly or indirectly from any of the following which you do\nor cause to occur: (a) distribution of this or any Project Gutenberg-tm\nwork, (b) alteration, modification, or additions or deletions to any\nProject Gutenberg-tm work, and (c) any Defect you cause.\n\n\nSection  2.  Information about the Mission of Project Gutenberg-tm\n\nProject Gutenberg-tm is synonymous with the free distribution of\nelectronic works in formats readable by the widest variety of computers\nincluding obsolete, old, middle-aged and new computers.  It exists\nbecause of the efforts of hundreds of volunteers and donations from\npeople in all walks of life.\n\nVolunteers and financial support to provide volunteers with the\nassistance they need, is critical to reaching Project Gutenberg-tm's\ngoals and ensuring that the Project Gutenberg-tm collection will\nremain freely available for generations to come.  In 2001, the Project\nGutenberg Literary Archive Foundation was created to provide a secure\nand permanent future for Project Gutenberg-tm and future generations.\nTo learn more about the Project Gutenberg Literary Archive Foundation\nand how your efforts and donations can help, see Sections 3 and 4\nand the Foundation web page at http://www.pglaf.org.\n\n\nSection 3.  Information about the Project Gutenberg Literary Archive\nFoundation\n\nThe Project Gutenberg Literary Archive Foundation is a non profit\n501(c)(3) educational corporation organized under the laws of the\nstate of Mississippi and granted tax exempt status by the Internal\nRevenue Service.  The Foundation's EIN or federal tax identification\nnumber is 64-6221541.  Its 501(c)(3) letter is posted at\nhttp://pglaf.org/fundraising.  Contributions to the Project Gutenberg\nLiterary Archive Foundation are tax deductible to the full extent\npermitted by U.S. federal laws and your state's laws.\n\nThe Foundation's principal office is located at 4557 Melan Dr. S.\nFairbanks, AK, 99712., but its volunteers and employees are scattered\nthroughout numerous locations.  Its business office is located at\n809 North 1500 West, Salt Lake City, UT 84116, (801) 596-1887, email\nbusiness@pglaf.org.  Email contact links and up to date contact\ninformation can be found at the Foundation's web site and official\npage at http://pglaf.org\n\nFor additional contact information:\n     Dr. Gregory B. Newby\n     Chief Executive and Director\n     gbnewby@pglaf.org\n\n\nSection 4.  Information about Donations to the Project Gutenberg\nLiterary Archive Foundation\n\nProject Gutenberg-tm depends upon and cannot survive without wide\nspread public support and donations to carry out its mission of\nincreasing the number of public domain and licensed works that can be\nfreely distributed in machine readable form accessible by the widest\narray of equipment including outdated equipment.  Many small donations\n($1 to $5,000) are particularly important to maintaining tax exempt\nstatus with the IRS.\n\nThe Foundation is committed to complying with the laws regulating\ncharities and charitable donations in all 50 states of the United\nStates.  Compliance requirements are not uniform and it takes a\nconsiderable effort, much paperwork and many fees to meet and keep up\nwith these requirements.  We do not solicit donations in locations\nwhere we have not received written confirmation of compliance.  To\nSEND DONATIONS or determine the status of compliance for any\nparticular state visit http://pglaf.org\n\nWhile we cannot and do not solicit contributions from states where we\nhave not met the solicitation requirements, we know of no prohibition\nagainst accepting unsolicited donations from donors in such states who\napproach us with offers to donate.\n\nInternational donations are gratefully accepted, but we cannot make\nany statements concerning tax treatment of donations received from\noutside the United States.  U.S. laws alone swamp our small staff.\n\nPlease check the Project Gutenberg Web pages for current donation\nmethods and addresses.  Donations are accepted in a number of other\nways including including checks, online payments and credit card\ndonations.  To donate, please visit: http://pglaf.org/donate\n\n\nSection 5.  General Information About Project Gutenberg-tm electronic\nworks.\n\nProfessor Michael S. Hart is the originator of the Project Gutenberg-tm\nconcept of a library of electronic works that could be freely shared\nwith anyone.  For thirty years, he produced and distributed Project\nGutenberg-tm eBooks with only a loose network of volunteer support.\n\n\nProject Gutenberg-tm eBooks are often created from several printed\neditions, all of which are confirmed as Public Domain in the U.S.\nunless a copyright notice is included.  Thus, we do not necessarily\nkeep eBooks in compliance with any particular paper edition.\n\n\nMost people start at our Web site which has the main PG search facility:\n\n     http://www.gutenberg.net\n\nThis Web site includes information about Project Gutenberg-tm,\nincluding how to make donations to the Project Gutenberg Literary\nArchive Foundation, how to help produce our new eBooks, and how to\nsubscribe to our email newsletter to hear about new eBooks.\n"
  },
  {
    "path": "test/fixtures/files/get_files_id.json",
    "content": "{\n    \"type\": \"file\",\n    \"id\": \"1234567890\",\n    \"file_version\": {\n        \"type\": \"file_version\",\n        \"id\": \"11223344556677\",\n        \"sha1\": \"97b3dbba6eab7ad0f058240744c8636b7c7bea93\"\n    },\n    \"sequence_id\": \"1\",\n    \"etag\": \"1\",\n    \"sha1\": \"97b3dbba6eab7ad0f058240744c8636b7c7bea93\",\n    \"name\": \"test_file_download.txt\",\n    \"description\": \"\",\n    \"size\": 295191,\n    \"path_collection\": {\n        \"total_count\": 2,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"987654321\",\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"name\": \"Collaborated Folder\"\n            }\n        ]\n    },\n    \"created_at\": \"2016-11-16T22:01:44-08:00\",\n    \"modified_at\": \"2016-11-16T22:01:51-08:00\",\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": \"2016-10-29T18:33:50-07:00\",\n    \"content_modified_at\": \"2016-10-29T18:33:50-07:00\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"shared_link\": null,\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"987654321\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"Collaborated Folder\"\n    },\n    \"item_status\": \"active\"\n}\n"
  },
  {
    "path": "test/fixtures/files/get_files_id_collaborations_page_1.json",
    "content": "{\n\t\"next_marker\": \"ZAED53D\",\n\t\"previous_marker\": \"\",\n\t\"entries\": [\n\t\t{\n\t\t\t\"type\": \"collaboration\",\n\t\t\t\"id\": \"13421432143\",\n\t\t\t\"created_by\": {\n\t\t\t\t\"type\": \"user\",\n\t\t\t\t\"id\": \"11111\",\n\t\t\t\t\"name\": \"Bob Dylan\",\n\t\t\t\t\"login\": \"bob.dylan@gmail.com\"\n\t\t\t},\n\t\t\t\"created_at\": \"2018-06-08T11:48:21-07:00\",\n\t\t\t\"modified_at\": \"2018-06-11T13:03:45-07:00\",\n\t\t\t\"expires_at\": null,\n\t\t\t\"status\": \"accepted\",\n\t\t\t\"accessible_by\": {\n\t\t\t\t\"type\": \"user\",\n\t\t\t\t\"id\": \"22222\",\n\t\t\t\t\"name\": \"Steve Jobs\",\n\t\t\t\t\"login\": \"steve.jobs@microsoft.com\"\n\t\t\t},\n\t\t\t\"role\": \"editor\",\n\t\t\t\"acknowledged_at\": \"2018-06-08T11:48:21-07:00\",\n\t\t\t\"item\": {\n\t\t\t\t\"type\": \"file\",\n\t\t\t\t\"id\": \"1234567890\",\n\t\t\t\t\"file_version\": {\n\t\t\t\t\t\"type\": \"file_version\",\n\t\t\t\t\t\"id\": \"32132131431\",\n\t\t\t\t\t\"sha1\": \"34134214j321h432j14h321\"\n\t\t\t\t},\n\t\t\t\t\"sequence_id\": \"234\",\n\t\t\t\t\"etag\": \"234\",\n\t\t\t\t\"sha1\": \"32413h214j32141h32\",\n\t\t\t\t\"name\": \"Collab.boxnote\"\n\t\t\t}\n        },\n\t\t{\n\t\t\t\"type\": \"collaboration\",\n\t\t\t\"id\": \"13421432143\",\n\t\t\t\"created_by\": {\n\t\t\t\t\"type\": \"user\",\n\t\t\t\t\"id\": \"11111\",\n\t\t\t\t\"name\": \"Bob Dylan\",\n\t\t\t\t\"login\": \"bob.dylan@gmail.com\"\n\t\t\t},\n\t\t\t\"created_at\": \"2018-06-08T11:48:21-07:00\",\n\t\t\t\"modified_at\": \"2018-06-11T13:03:45-07:00\",\n\t\t\t\"expires_at\": null,\n\t\t\t\"status\": \"accepted\",\n\t\t\t\"accessible_by\": {\n\t\t\t\t\"type\": \"user\",\n\t\t\t\t\"id\": \"22222\",\n\t\t\t\t\"name\": \"Steve Jobs\",\n\t\t\t\t\"login\": \"steve.jobs@microsoft.com\"\n\t\t\t},\n\t\t\t\"role\": \"editor\",\n\t\t\t\"acknowledged_at\": \"2018-06-08T11:48:21-07:00\",\n\t\t\t\"item\": {\n\t\t\t\t\"type\": \"file\",\n\t\t\t\t\"id\": \"1234567890\",\n\t\t\t\t\"file_version\": {\n\t\t\t\t\t\"type\": \"file_version\",\n\t\t\t\t\t\"id\": \"32132131431\",\n\t\t\t\t\t\"sha1\": \"34134214j321h432j14h321\"\n\t\t\t\t},\n\t\t\t\t\"sequence_id\": \"234\",\n\t\t\t\t\"etag\": \"234\",\n\t\t\t\t\"sha1\": \"32413h214j32141h32\",\n\t\t\t\t\"name\": \"Collab.boxnote\"\n\t\t\t}\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/files/get_files_id_collaborations_page_2.json",
    "content": "{\n\t\"next_marker\": \"\",\n\t\"previous_marker\": \"\",\n\t\"entries\": [\n\t\t{\n\t\t\t\"type\": \"collaboration\",\n\t\t\t\"id\": \"1342143214678\",\n\t\t\t\"created_by\": {\n\t\t\t\t\"type\": \"user\",\n\t\t\t\t\"id\": \"11111\",\n\t\t\t\t\"name\": \"Bob Dylan\",\n\t\t\t\t\"login\": \"bob.dylan@gmail.com\"\n\t\t\t},\n\t\t\t\"created_at\": \"2018-06-08T11:48:21-07:00\",\n\t\t\t\"modified_at\": \"2018-06-11T13:03:45-07:00\",\n\t\t\t\"expires_at\": null,\n\t\t\t\"status\": \"accepted\",\n\t\t\t\"accessible_by\": {\n\t\t\t\t\"type\": \"user\",\n\t\t\t\t\"id\": \"22222\",\n\t\t\t\t\"name\": \"Steve Jobs\",\n\t\t\t\t\"login\": \"steve.jobs@microsoft.com\"\n\t\t\t},\n\t\t\t\"role\": \"editor\",\n\t\t\t\"acknowledged_at\": \"2018-06-08T11:48:21-07:00\",\n\t\t\t\"item\": {\n\t\t\t\t\"type\": \"file\",\n\t\t\t\t\"id\": \"1234567890\",\n\t\t\t\t\"file_version\": {\n\t\t\t\t\t\"type\": \"file_version\",\n\t\t\t\t\t\"id\": \"32132131431\",\n\t\t\t\t\t\"sha1\": \"34134214j321h432j14h321\"\n\t\t\t\t},\n\t\t\t\t\"sequence_id\": \"234\",\n\t\t\t\t\"etag\": \"234\",\n\t\t\t\t\"sha1\": \"32413h214j32141h32\",\n\t\t\t\t\"name\": \"Collab.boxnote\"\n\t\t\t}\n        },\n\t\t{\n\t\t\t\"type\": \"collaboration\",\n\t\t\t\"id\": \"134214321764\",\n\t\t\t\"created_by\": {\n\t\t\t\t\"type\": \"user\",\n\t\t\t\t\"id\": \"11111\",\n\t\t\t\t\"name\": \"Bob Dylan\",\n\t\t\t\t\"login\": \"bob.dylan@gmail.com\"\n\t\t\t},\n\t\t\t\"created_at\": \"2018-06-08T11:48:21-07:00\",\n\t\t\t\"modified_at\": \"2018-06-11T13:03:45-07:00\",\n\t\t\t\"expires_at\": null,\n\t\t\t\"status\": \"accepted\",\n\t\t\t\"accessible_by\": {\n\t\t\t\t\"type\": \"user\",\n\t\t\t\t\"id\": \"22222\",\n\t\t\t\t\"name\": \"Steve Jobs\",\n\t\t\t\t\"login\": \"steve.jobs@microsoft.com\"\n\t\t\t},\n\t\t\t\"role\": \"editor\",\n\t\t\t\"acknowledged_at\": \"2018-06-08T11:48:21-07:00\",\n\t\t\t\"item\": {\n\t\t\t\t\"type\": \"file\",\n\t\t\t\t\"id\": \"1234567890\",\n\t\t\t\t\"file_version\": {\n\t\t\t\t\t\"type\": \"file_version\",\n\t\t\t\t\t\"id\": \"32132131431\",\n\t\t\t\t\t\"sha1\": \"34134214j321h432j14h321\"\n\t\t\t\t},\n\t\t\t\t\"sequence_id\": \"234\",\n\t\t\t\t\"etag\": \"234\",\n\t\t\t\t\"sha1\": \"32413h214j32141h32\",\n\t\t\t\t\"name\": \"Collab.boxnote\"\n\t\t\t}\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/files/get_files_id_metadata.json",
    "content": "{\n    \"entries\": [\n        {\n            \"$type\": \"testTemplate-2890e928-874d-4959-afb7-6a778b3ad75c\",\n            \"$parent\": \"file_11111\",\n            \"$id\": \"ff8cb88e-de80-467c-aa02-412c1cdaee48\",\n            \"$version\": 1,\n            \"$typeVersion\": 0,\n            \"testEnum\": \"foo\",\n            \"$template\": \"testTemplate\",\n            \"$scope\": \"enterprise_22222\"\n        }\n    ],\n    \"limit\": 100\n}\n"
  },
  {
    "path": "test/fixtures/files/get_files_id_metadata_scope_template.json",
    "content": "{\n    \"$type\": \"testTemplate-2890e938-874d-4059-afc7-6a778b3ad75c\",\n    \"$parent\": \"file_11111\",\n    \"$id\": \"ff8ab88e-de80-567c-aa02-412c1cdaee36\",\n    \"$version\": 1,\n    \"$typeVersion\": 0,\n    \"testEnum\": \"foo\",\n    \"$template\": \"testTemplate\",\n    \"$scope\": \"enterprise_22222\"\n}\n"
  },
  {
    "path": "test/fixtures/files/get_files_id_tasks_page_1.json",
    "content": "{\n    \"total_count\": 2,\n    \"entries\": [\n        {\n            \"type\": \"task\",\n            \"id\": \"11111\",\n            \"item\": {\n                \"type\": \"file\",\n                \"id\": \"1234567890\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"22222\",\n                    \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n                },\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n                \"name\": \"Tasks file.txt\"\n            },\n            \"due_at\": null\n        }\n    ],\n\t\"limit\": 1,\n\t\"offset\": 0\n}"
  },
  {
    "path": "test/fixtures/files/get_files_id_tasks_page_2.json",
    "content": "{\n    \"total_count\": 2,\n    \"entries\": [\n        {\n            \"type\": \"task\",\n            \"id\": \"111112\",\n            \"item\": {\n                \"type\": \"file\",\n                \"id\": \"1234567890\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"22222\",\n                    \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n                },\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n                \"name\": \"Tasks file.txt\"\n            },\n            \"due_at\": null\n        }\n    ],\n\t\"limit\": 1,\n\t\"offset\": 1\n}"
  },
  {
    "path": "test/fixtures/files/get_files_id_versions_page_1.json",
    "content": "{\n    \"total_count\": 4,\n    \"entries\": [\n        {\n            \"type\": \"file_version\",\n            \"id\": \"11111\",\n            \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n            \"name\": \"test file.txt\",\n            \"size\": 16,\n            \"created_at\": \"2016-12-07T15:59:32-08:00\",\n            \"modified_at\": \"2016-12-07T15:59:32-08:00\",\n            \"modified_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"trashed_at\": null,\n            \"purged_at\": null\n        },\n        {\n            \"type\": \"file_version\",\n            \"id\": \"22222\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"test file.txt\",\n            \"size\": 9,\n            \"created_at\": \"2016-12-07T15:53:59-08:00\",\n            \"modified_at\": \"2016-12-07T15:53:59-08:00\",\n            \"modified_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"trashed_at\": null,\n            \"purged_at\": null\n        }\n    ],\n    \"limit\": 2,\n    \"offset\": 0\n}"
  },
  {
    "path": "test/fixtures/files/get_files_id_versions_page_2.json",
    "content": "{\n    \"total_count\": 4,\n    \"entries\": [\n        {\n            \"type\": \"file_version\",\n            \"id\": \"111112\",\n            \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n            \"name\": \"test file.txt\",\n            \"size\": 16,\n            \"created_at\": \"2016-12-07T15:59:32-08:00\",\n            \"modified_at\": \"2016-12-07T15:59:32-08:00\",\n            \"modified_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"trashed_at\": null,\n            \"purged_at\": null\n        },\n        {\n            \"type\": \"file_version\",\n            \"id\": \"222223\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"test file.txt\",\n            \"size\": 9,\n            \"created_at\": \"2016-12-07T15:53:59-08:00\",\n            \"modified_at\": \"2016-12-07T15:53:59-08:00\",\n            \"modified_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"trashed_at\": null,\n            \"purged_at\": null\n        }\n    ],\n    \"limit\": 2,\n    \"offset\": 2\n}"
  },
  {
    "path": "test/fixtures/files/get_zip_downloads_status.json",
    "content": "{\n    \"total_file_count\": 20,\n    \"downloaded_file_count\": 20,\n    \"skipped_files_count\": 10,\n    \"skipped_folder_count\": 10,\n    \"state\": \"succeeded\"\n}\n"
  },
  {
    "path": "test/fixtures/files/post_collaborations_user.json",
    "content": "{\n    \"type\": \"collaboration\",\n    \"id\": \"1234567890\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"9753108642\",\n        \"name\": \"Inviting User\",\n        \"login\": \"invites@example.com\"\n    },\n    \"created_at\": \"2016-11-16T21:33:31-08:00\",\n    \"modified_at\": \"2016-11-16T21:33:31-08:00\",\n    \"expires_at\": null,\n    \"status\": \"accepted\",\n    \"accessible_by\": {\n        \"type\": \"user\",\n        \"id\": \"987654321\",\n        \"name\": \"My New Friend\",\n        \"login\": \"newfriend@example.com\"\n    },\n    \"role\": \"previewer\",\n    \"acknowledged_at\": \"2016-11-16T21:33:31-08:00\",\n    \"item\": {\n        \"type\": \"file\",\n        \"id\": \"1234567890\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"Collaborated File\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/files/post_files_content.json",
    "content": "{\n    \"total_count\":1,\n    \"entries\":[\n        {\n            \"type\":\"file\",\n            \"id\":\"1234567890\",\n            \"file_version\":{\n                \"type\":\"file_version\",\n                \"id\":\"098765432109\",\n                \"sha1\":\"0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33\"\n            },\n            \"sequence_id\":\"0\",\n            \"etag\":\"0\",\n            \"sha1\":\"0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33\",\n            \"name\":\"file.txt\",\n            \"description\":\"\",\n            \"size\":3,\n            \"path_collection\":{\n                \"total_count\":1,\n                \"entries\":[\n                    {\n                        \"type\":\"folder\",\n                        \"id\":\"0\",\n                        \"sequence_id\":null,\n                        \"etag\":null,\n                        \"name\":\"All Files\"\n                    }\n                ]\n            },\n            \"created_at\":\"2017-05-16T15:18:02-07:00\",\n            \"modified_at\":\"2017-05-16T15:18:02-07:00\",\n            \"trashed_at\":null,\n            \"purged_at\":null,\n            \"content_created_at\":\"2017-05-16T15:18:02-07:00\",\n            \"content_modified_at\":\"2017-05-16T15:18:02-07:00\",\n            \"created_by\":{\n                \"type\":\"user\",\n                \"id\":\"123456789\",\n                \"name\":\"Test User\",\n                \"login\":\"test@example.com\"\n            },\n            \"modified_by\":{\n                \"type\":\"user\",\n                \"id\":\"123456789\",\n                \"name\":\"Test User\",\n                \"login\":\"test@example.com\"\n            },\n            \"owned_by\":{\n                \"type\":\"user\",\n                \"id\":\"123456789\",\n                \"name\":\"Test User\",\n                \"login\":\"test@example.com\"\n            },\n            \"shared_link\":null,\n            \"parent\":{\n                \"type\":\"user\",\n                \"id\":\"123456789\",\n                \"name\":\"Test User\",\n                \"login\":\"test@example.com\"\n            },\n            \"item_status\":\"active\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/files/post_files_id_copy.json",
    "content": "{\n    \"type\": \"file\",\n    \"id\": \"1234567890\",\n    \"file_version\": {\n        \"type\": \"file_version\",\n        \"id\": \"11223344556677\",\n        \"sha1\": \"97b3dbba6eab7ad0f058240744c8636b7c7bea93\"\n    },\n    \"sequence_id\": \"2\",\n    \"etag\": \"2\",\n    \"sha1\": \"97b3dbba6eab7ad0f058240744c8636b7c7bea93\",\n    \"name\": \"Dog.png\",\n    \"description\": \"\",\n    \"size\": 106833,\n    \"path_collection\": {\n        \"total_count\": 2,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"987654321\",\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"name\": \"Collaborated Folder\"\n            }\n        ]\n    },\n    \"created_at\": \"2016-11-16T22:01:44-08:00\",\n    \"modified_at\": \"2016-11-16T23:23:57-08:00\",\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": \"2016-10-29T18:33:50-07:00\",\n    \"content_modified_at\": \"2016-10-29T18:33:50-07:00\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"shared_link\": null,\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"987654321\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"Collaborated Folder\"\n    },\n    \"item_status\": \"active\"\n}\n"
  },
  {
    "path": "test/fixtures/files/post_files_id_metadata_scope_template.json",
    "content": "{\n    \"test\": \"test123\",\n    \"number\": 1.9,\n    \"$type\": \"testTemplate-2890e938-874d-4959-bbc7-6a778b3ad75c\",\n    \"$parent\": \"file_11111\",\n    \"$id\": \"89b3a698-7705-3152-9c25-73f789a1b924\",\n    \"$version\": 0,\n    \"$typeVersion\": 0,\n    \"$template\": \"testTemplate\",\n    \"$scope\": \"enterprise_22222\"\n}\n"
  },
  {
    "path": "test/fixtures/files/post_files_id_versions_current.json",
    "content": "{\n    \"type\": \"file_version\",\n    \"id\": \"1234567890\",\n    \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n    \"name\": \"test file.txt\",\n    \"size\": 16,\n    \"created_at\": \"2018-04-24T15:08:58-07:00\",\n    \"modified_at\": \"2018-04-24T15:08:58-07:00\",\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"trashed_at\": null,\n    \"purged_at\": null\n}\n"
  },
  {
    "path": "test/fixtures/files/post_zip_downloads.json",
    "content": "{\n\t\"download_url\": \"https://dl.boxcloud.com/2.0/zip_downloads/124hfiowk3fa8kmrwh/content\",\n\t\"status_url\": \"https://api.box.com/2.0/zip_downloads/124hfiowk3fa8kmrwh/status\",\n\t\"expires_at\": \"2018-04-25T11:00:18-07:00\",\n\t\"name_conflicts\": [\n\t\t[\n\t\t\t{\n\t\t\t\t\"id\": \"100\",\n\t\t\t\t\"type\": \"file\",\n\t\t\t\t\"original_name\": \"salary.pdf\",\n\t\t\t\t\"download_name\": \"aqc823.pdf\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"id\": \"200\",\n\t\t\t\t\"type\": \"file\",\n\t\t\t\t\"original_name\": \"salary.pdf\",\n\t\t\t\t\"download_name\": \"aci23s.pdf\"\n\t\t\t}\n\t\t],\n\t\t[\n\t\t\t{\n\t\t\t\t\"id\": \"1000\",\n\t\t\t\t\"type\": \"folder\",\n\t\t\t\t\"original_name\": \"employees\",\n\t\t\t\t\"download_name\": \"3d366a_employees\"\n\t\t\t},\n\t\t\t{\n\t\t\t\t\"id\": \"2000\",\n\t\t\t\t\"type\": \"folder\",\n\t\t\t\t\"original_name\": \"employees\",\n\t\t\t\t\"download_name\": \"3aa6a7_employees\"\n\t\t\t}\n\t\t]\n\t]\n}"
  },
  {
    "path": "test/fixtures/files/put_collaborations_id.json",
    "content": "{\n    \"type\": \"collaboration\",\n    \"id\": \"1234567890\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"834098476\",\n        \"name\": \"Inviting User\",\n        \"login\": \"inviter@example.com\"\n    },\n    \"created_at\": \"2015-11-03T18:36:37-08:00\",\n    \"modified_at\": \"2016-11-16T21:01:19-08:00\",\n    \"expires_at\": null,\n    \"status\": \"accepted\",\n    \"accessible_by\": {\n        \"type\": \"user\",\n        \"id\": \"6789234576\",\n        \"name\": \"Collaborated User\",\n        \"login\": \"collaborator@example.com\"\n    },\n    \"role\": \"viewer uploader\",\n    \"acknowledged_at\": \"2015-11-03T18:36:37-08:00\",\n    \"item\": {\n        \"type\": \"folder\",\n        \"id\": \"9087654321\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"name\": \"Collaborated Folder\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/files/put_files_id.json",
    "content": "{\n    \"type\": \"file\",\n    \"id\": \"1234567890\",\n    \"file_version\": {\n        \"type\": \"file_version\",\n        \"id\": \"11223344556677\",\n        \"sha1\": \"97b3dbba6eab7ad0f058240744c8636b7c7bea93\"\n    },\n    \"sequence_id\": \"2\",\n    \"etag\": \"2\",\n    \"sha1\": \"97b3dbba6eab7ad0f058240744c8636b7c7bea93\",\n    \"name\": \"test\",\n    \"description\": \"test_description\",\n    \"size\": 106833,\n    \"path_collection\": {\n        \"total_count\": 2,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"987654321\",\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"name\": \"Collaborated Folder\"\n            }\n        ]\n    },\n    \"created_at\": \"2016-11-16T22:01:44-08:00\",\n    \"modified_at\": \"2016-11-16T23:23:57-08:00\",\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": \"2016-10-29T18:33:50-07:00\",\n    \"content_modified_at\": \"2016-10-29T18:33:50-07:00\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"shared_link\": null,\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"987654321\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"Collaborated Folder\"\n    },\n    \"item_status\": \"active\"\n}\n"
  },
  {
    "path": "test/fixtures/files/put_files_id_lock.json",
    "content": "{\n    \"type\": \"file\",\n    \"id\": \"1234567890\",\n    \"file_version\": {\n        \"type\": \"file_version\",\n        \"id\": \"22222\",\n        \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n    },\n    \"sequence_id\": \"0\",\n    \"etag\": \"0\",\n    \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n    \"name\": \"Lock file.txt\",\n    \"description\": \"\",\n    \"size\": 9,\n    \"path_collection\": {\n        \"total_count\": 1,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            }\n        ]\n    },\n    \"created_at\": \"2016-12-07T15:56:54-08:00\",\n    \"modified_at\": \"2016-12-07T15:56:54-08:00\",\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": \"2016-12-07T15:53:59-08:00\",\n    \"content_modified_at\": \"2016-12-07T15:53:59-08:00\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"shared_link\": null,\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"0\",\n        \"sequence_id\": null,\n        \"etag\": null,\n        \"name\": \"All Files\"\n    },\n    \"item_status\": \"active\"\n}\n"
  },
  {
    "path": "test/fixtures/files/put_files_id_shared_link.json",
    "content": "{\n    \"type\": \"file\",\n    \"id\": \"1234567890\",\n    \"shared_link\": {\n        \"url\": \"https://blosserdemoaccount.box.com/s/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p\",\n        \"download_url\": \"https://blosserdemoaccount.box.com/shared/static/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p.png\",\n        \"vanity_url\": \"https://app.box.com/v/my-custom-name-123\",\n        \"effective_access\": \"open\",\n        \"is_password_enabled\": true,\n        \"unshared_at\": null,\n        \"download_count\": 0,\n        \"preview_count\": 0,\n        \"access\": \"test\",\n        \"permissions\": {\n            \"can_download\": true,\n            \"can_preview\": true,\n            \"can_edit\": true\n        }\n    }\n}\n"
  },
  {
    "path": "test/fixtures/files/test_file.txt",
    "content": "hello"
  },
  {
    "path": "test/fixtures/folders/get_folder_locks.json",
    "content": "{\n\t\"entries\": [\n\t\t{\n\t\t\t\"folder\": {\n\t\t\t\t\"id\": \"12345\",\n\t\t\t\t\"etag\": \"1\",\n\t\t\t\t\"type\": \"folder\",\n\t\t\t\t\"sequence_id\": \"3\",\n\t\t\t\t\"name\": \"Contracts\"\n\t\t\t},\n\t\t\t\"id\": \"12345678\",\n\t\t\t\"type\": \"folder_lock\",\n\t\t\t\"created_by\": {\n\t\t\t\t\"id\": \"11446498\",\n\t\t\t\t\"type\": \"user\"\n\t\t\t},\n\t\t\t\"created_at\": \"2020-09-14T23:12:53Z\",\n\t\t\t\"locked_operations\": {\n\t\t\t\t\"move\": true,\n\t\t\t\t\"delete\": true\n\t\t\t},\n\t\t\t\"lock_type\": \"freeze\"\n\t\t}\n\t],\n\t\"limit\": 1000,\n\t\"next_marker\": null\n}\n"
  },
  {
    "path": "test/fixtures/folders/get_folders_id.json",
    "content": "{\n    \"type\": \"folder\",\n    \"id\": \"0\",\n    \"sequence_id\": null,\n    \"etag\": null,\n    \"name\": \"All Files\",\n    \"created_at\": null,\n    \"modified_at\": null,\n    \"description\": \"\",\n    \"size\": 8183737,\n    \"path_collection\": {\n        \"total_count\": 0,\n        \"entries\": []\n    },\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"\",\n        \"name\": \"\",\n        \"login\": \"\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": null,\n    \"content_modified_at\": null,\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"shared_link\": null,\n    \"folder_upload_email\": null,\n    \"parent\": null,\n    \"item_status\": \"active\",\n    \"item_collection\": {\n        \"total_count\": 6,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"44444\",\n                \"sequence_id\": \"1\",\n                \"etag\": \"1\",\n                \"name\": \"Collab Folder\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"55555\",\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"name\": \"Copied Folder\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"66666\",\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"name\": \"SDK Test Folder\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"77777\",\n                \"sequence_id\": \"1\",\n                \"etag\": \"1\",\n                \"name\": \"Test Folder\"\n            },\n            {\n                \"type\": \"file\",\n                \"id\": \"88888\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"888880\",\n                    \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n                },\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n                \"name\": \"Copied file.txt\"\n            },\n            {\n                \"type\": \"file\",\n                \"id\": \"99999\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"999990\",\n                    \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n                },\n                \"sequence_id\": \"9\",\n                \"etag\": \"9\",\n                \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n                \"name\": \"test file.txt\"\n            }\n        ],\n        \"offset\": 0,\n        \"limit\": 100,\n        \"order\": [\n            {\n                \"by\": \"type\",\n                \"direction\": \"ASC\"\n            },\n            {\n                \"by\": \"name\",\n                \"direction\": \"ASC\"\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": "test/fixtures/folders/get_folders_id_collaborations.json",
    "content": "{\n    \"total_count\": 1,\n    \"entries\": [\n        {\n            \"type\": \"collaboration\",\n            \"id\": \"12345\",\n            \"created_by\": null,\n            \"created_at\": \"2016-11-16T21:48:44-08:00\",\n            \"modified_at\": \"2016-11-16T21:48:44-08:00\",\n            \"expires_at\": null,\n            \"status\": \"accepted\",\n            \"accessible_by\": {\n                \"type\": \"group\",\n                \"id\": \"22222\",\n                \"name\": \"Employees\",\n                \"group_type\": \"managed_group\"\n            },\n            \"role\": \"editor\",\n            \"acknowledged_at\": \"2016-11-16T21:48:44-08:00\",\n            \"item\": {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": \"1\",\n                \"etag\": \"1\",\n                \"name\": \"Collab Folder\"\n            }\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/folders/get_folders_id_folder_download.json",
    "content": "{\n    \"type\": \"folder\",\n    \"id\": \"11111\",\n    \"sequence_id\": \"0\",\n    \"etag\": \"0\",\n    \"name\": \"DownloadFolderTest\",\n    \"created_at\": \"2018-09-19T09:20:37-07:00\",\n    \"modified_at\": \"2018-09-19T09:20:37-07:00\",\n    \"description\": \"\",\n    \"size\": 8183737,\n    \"path_collection\": {\n        \"total_count\": 1,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"name\": \"All Files\"\n            }\n        ]\n    },\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": null,\n    \"content_modified_at\": null,\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"shared_link\": null,\n    \"folder_upload_email\": null,\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"0\",\n        \"name\": \"All Files\"\n    },\n    \"item_status\": \"active\",\n    \"item_collection\": {\n        \"total_count\": 3,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"22222\",\n                \"sequence_id\": \"1\",\n                \"etag\": \"1\",\n                \"name\": \"subfolder\"\n            },\n            {\n                \"type\": \"file\",\n                \"id\": \"44444\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"444441\",\n                    \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n                },\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n                \"name\": \"file 1.txt\"\n            },\n            {\n                \"type\": \"file\",\n                \"id\": \"55555\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"555551\",\n                    \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n                },\n                \"sequence_id\": \"9\",\n                \"etag\": \"9\",\n                \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n                \"name\": \"file 2.txt\"\n            }\n        ],\n        \"offset\": 0,\n        \"limit\": 100,\n        \"order\": [\n            {\n                \"by\": \"type\",\n                \"direction\": \"ASC\"\n            },\n            {\n                \"by\": \"name\",\n                \"direction\": \"ASC\"\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": "test/fixtures/folders/get_folders_id_items.json",
    "content": "{\n    \"total_count\": 5,\n    \"entries\": [\n        {\n            \"type\": \"folder\",\n            \"id\": \"1234567\",\n            \"sequence_id\": \"10\",\n            \"etag\": \"10\",\n            \"name\": \"Box\"\n        },\n        {\n            \"type\": \"folder\",\n            \"id\": \"22585432\",\n            \"sequence_id\": \"9\",\n            \"etag\": \"9\",\n            \"name\": \"Human Resources\"\n        },\n        {\n            \"type\": \"folder\",\n            \"id\": \"24432981\",\n            \"sequence_id\": \"8\",\n            \"etag\": \"8\",\n            \"name\": \"Engineering\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"124000\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"431000\",\n                \"sha1\": \"b7e432rew9bc2850a5780a86a25a8574d1b473f\"\n            },\n            \"sequence_id\": \"79\",\n            \"etag\": \"79\",\n            \"sha1\": \"b7e9fsdfe329bc2850a5780a86a25a8574d1b473f\",\n            \"name\": \"Draymond.boxnote\"\n        },\n        {\n            \"type\": \"web_link\",\n            \"id\": \"13413421543\",\n            \"sequence_id\": \"77\",\n            \"etag\": \"77\",\n            \"name\": \"77 Crunchy Dragon Rolls\",\n            \"url\": \"https://cloud.app.box.com/s/432fesr32fsdfw\"\n        }\n    ],\n    \"next_marker\": null,\n    \"order\": [\n        {\n            \"by\": \"type\",\n            \"direction\": \"ASC\"\n        },\n        {\n            \"by\": \"name\",\n            \"direction\": \"ASC\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/folders/get_folders_id_items_page_1.json",
    "content": "{\n    \"total_count\": 6,\n    \"entries\": [\n        {\n            \"type\": \"folder\",\n            \"id\": \"11111\",\n            \"sequence_id\": \"1\",\n            \"etag\": \"1\",\n            \"name\": \"Collab Folder\"\n        },\n        {\n            \"type\": \"folder\",\n            \"id\": \"22222\",\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"name\": \"Copied Folder\"\n        },\n        {\n            \"type\": \"folder\",\n            \"id\": \"33333\",\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"name\": \"SDK Test Folder\"\n        },\n        {\n            \"type\": \"folder\",\n            \"id\": \"44444\",\n            \"sequence_id\": \"1\",\n            \"etag\": \"1\",\n            \"name\": \"Test Folder\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"55555\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"555550\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"Copied file.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"66666\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"666660\",\n                \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n            },\n            \"sequence_id\": \"9\",\n            \"etag\": \"9\",\n            \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n            \"name\": \"test file.txt\"\n        }\n    ],\n    \"next_marker\": \"page_1_marker\",\n    \"order\": [\n        {\n            \"by\": \"type\",\n            \"direction\": \"ASC\"\n        },\n        {\n            \"by\": \"name\",\n            \"direction\": \"ASC\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/folders/get_folders_id_items_page_1_folder_download.json",
    "content": "{\n    \"entries\": [\n        {\n            \"type\": \"file\",\n            \"id\": \"1\",\n            \"etag\": \"1\",\n            \"name\": \"file 1.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"2\",\n            \"etag\": \"1\",\n            \"name\": \"file 2.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"3\",\n            \"etag\": \"1\",\n            \"name\": \"file 3.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"4\",\n            \"etag\": \"1\",\n            \"name\": \"file 4.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"5\",\n            \"etag\": \"1\",\n            \"name\": \"file 5.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"6\",\n            \"etag\": \"1\",\n            \"name\": \"file 6.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"7\",\n            \"etag\": \"1\",\n            \"name\": \"file 7.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"8\",\n            \"etag\": \"1\",\n            \"name\": \"file 8.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"9\",\n            \"etag\": \"1\",\n            \"name\": \"file 9.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"10\",\n            \"etag\": \"1\",\n            \"name\": \"file 10.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"11\",\n            \"etag\": \"1\",\n            \"name\": \"file 11.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"12\",\n            \"etag\": \"1\",\n            \"name\": \"file 12.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"13\",\n            \"etag\": \"1\",\n            \"name\": \"file 13.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"14\",\n            \"etag\": \"1\",\n            \"name\": \"file 14.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"15\",\n            \"etag\": \"1\",\n            \"name\": \"file 15.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"16\",\n            \"etag\": \"1\",\n            \"name\": \"file 16.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"17\",\n            \"etag\": \"1\",\n            \"name\": \"file 17.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"18\",\n            \"etag\": \"1\",\n            \"name\": \"file 18.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"19\",\n            \"etag\": \"1\",\n            \"name\": \"file 19.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"20\",\n            \"etag\": \"1\",\n            \"name\": \"file 20.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"21\",\n            \"etag\": \"1\",\n            \"name\": \"file 21.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"22\",\n            \"etag\": \"1\",\n            \"name\": \"file 22.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"23\",\n            \"etag\": \"1\",\n            \"name\": \"file 23.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"24\",\n            \"etag\": \"1\",\n            \"name\": \"file 24.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"25\",\n            \"etag\": \"1\",\n            \"name\": \"file 25.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"26\",\n            \"etag\": \"1\",\n            \"name\": \"file 26.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"27\",\n            \"etag\": \"1\",\n            \"name\": \"file 27.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"28\",\n            \"etag\": \"1\",\n            \"name\": \"file 28.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"29\",\n            \"etag\": \"1\",\n            \"name\": \"file 29.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"30\",\n            \"etag\": \"1\",\n            \"name\": \"file 30.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"31\",\n            \"etag\": \"1\",\n            \"name\": \"file 31.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"32\",\n            \"etag\": \"1\",\n            \"name\": \"file 32.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"33\",\n            \"etag\": \"1\",\n            \"name\": \"file 33.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"34\",\n            \"etag\": \"1\",\n            \"name\": \"file 34.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"35\",\n            \"etag\": \"1\",\n            \"name\": \"file 35.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"36\",\n            \"etag\": \"1\",\n            \"name\": \"file 36.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"37\",\n            \"etag\": \"1\",\n            \"name\": \"file 37.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"38\",\n            \"etag\": \"1\",\n            \"name\": \"file 38.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"39\",\n            \"etag\": \"1\",\n            \"name\": \"file 39.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"40\",\n            \"etag\": \"1\",\n            \"name\": \"file 40.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"41\",\n            \"etag\": \"1\",\n            \"name\": \"file 41.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"42\",\n            \"etag\": \"1\",\n            \"name\": \"file 42.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"43\",\n            \"etag\": \"1\",\n            \"name\": \"file 43.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"44\",\n            \"etag\": \"1\",\n            \"name\": \"file 44.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"45\",\n            \"etag\": \"1\",\n            \"name\": \"file 45.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"46\",\n            \"etag\": \"1\",\n            \"name\": \"file 46.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"47\",\n            \"etag\": \"1\",\n            \"name\": \"file 47.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"48\",\n            \"etag\": \"1\",\n            \"name\": \"file 48.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"49\",\n            \"etag\": \"1\",\n            \"name\": \"file 49.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"50\",\n            \"etag\": \"1\",\n            \"name\": \"file 50.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"51\",\n            \"etag\": \"1\",\n            \"name\": \"file 51.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"52\",\n            \"etag\": \"1\",\n            \"name\": \"file 52.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"53\",\n            \"etag\": \"1\",\n            \"name\": \"file 53.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"54\",\n            \"etag\": \"1\",\n            \"name\": \"file 54.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"55\",\n            \"etag\": \"1\",\n            \"name\": \"file 55.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"56\",\n            \"etag\": \"1\",\n            \"name\": \"file 56.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"57\",\n            \"etag\": \"1\",\n            \"name\": \"file 57.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"58\",\n            \"etag\": \"1\",\n            \"name\": \"file 58.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"59\",\n            \"etag\": \"1\",\n            \"name\": \"file 59.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"60\",\n            \"etag\": \"1\",\n            \"name\": \"file 60.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"61\",\n            \"etag\": \"1\",\n            \"name\": \"file 61.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"62\",\n            \"etag\": \"1\",\n            \"name\": \"file 62.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"63\",\n            \"etag\": \"1\",\n            \"name\": \"file 63.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"64\",\n            \"etag\": \"1\",\n            \"name\": \"file 64.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"65\",\n            \"etag\": \"1\",\n            \"name\": \"file 65.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"66\",\n            \"etag\": \"1\",\n            \"name\": \"file 66.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"67\",\n            \"etag\": \"1\",\n            \"name\": \"file 67.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"68\",\n            \"etag\": \"1\",\n            \"name\": \"file 68.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"69\",\n            \"etag\": \"1\",\n            \"name\": \"file 69.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"70\",\n            \"etag\": \"1\",\n            \"name\": \"file 70.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"71\",\n            \"etag\": \"1\",\n            \"name\": \"file 71.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"72\",\n            \"etag\": \"1\",\n            \"name\": \"file 72.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"73\",\n            \"etag\": \"1\",\n            \"name\": \"file 73.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"74\",\n            \"etag\": \"1\",\n            \"name\": \"file 74.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"75\",\n            \"etag\": \"1\",\n            \"name\": \"file 75.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"76\",\n            \"etag\": \"1\",\n            \"name\": \"file 76.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"77\",\n            \"etag\": \"1\",\n            \"name\": \"file 77.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"78\",\n            \"etag\": \"1\",\n            \"name\": \"file 78.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"79\",\n            \"etag\": \"1\",\n            \"name\": \"file 79.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"80\",\n            \"etag\": \"1\",\n            \"name\": \"file 80.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"81\",\n            \"etag\": \"1\",\n            \"name\": \"file 81.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"82\",\n            \"etag\": \"1\",\n            \"name\": \"file 82.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"83\",\n            \"etag\": \"1\",\n            \"name\": \"file 83.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"84\",\n            \"etag\": \"1\",\n            \"name\": \"file 84.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"85\",\n            \"etag\": \"1\",\n            \"name\": \"file 85.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"86\",\n            \"etag\": \"1\",\n            \"name\": \"file 86.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"87\",\n            \"etag\": \"1\",\n            \"name\": \"file 87.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"88\",\n            \"etag\": \"1\",\n            \"name\": \"file 88.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"89\",\n            \"etag\": \"1\",\n            \"name\": \"file 89.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"90\",\n            \"etag\": \"1\",\n            \"name\": \"file 90.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"91\",\n            \"etag\": \"1\",\n            \"name\": \"file 91.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"92\",\n            \"etag\": \"1\",\n            \"name\": \"file 92.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"93\",\n            \"etag\": \"1\",\n            \"name\": \"file 93.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"94\",\n            \"etag\": \"1\",\n            \"name\": \"file 94.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"95\",\n            \"etag\": \"1\",\n            \"name\": \"file 95.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"96\",\n            \"etag\": \"1\",\n            \"name\": \"file 96.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"97\",\n            \"etag\": \"1\",\n            \"name\": \"file 97.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"98\",\n            \"etag\": \"1\",\n            \"name\": \"file 98.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"99\",\n            \"etag\": \"1\",\n            \"name\": \"file 99.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"100\",\n            \"etag\": \"1\",\n            \"name\": \"file 100.txt\"\n        }\n    ],\n    \"limit\": 100,\n    \"next_marker\": \"page_1_marker\",\n    \"order\": [\n        {\n            \"by\": \"name\",\n            \"direction\": \"ASC\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/folders/get_folders_id_items_page_2.json",
    "content": "{\n    \"total_count\": 6,\n    \"entries\": [\n        {\n            \"type\": \"folder\",\n            \"id\": \"111112\",\n            \"sequence_id\": \"1\",\n            \"etag\": \"1\",\n            \"name\": \"Collab Folder\"\n        },\n        {\n            \"type\": \"folder\",\n            \"id\": \"222223\",\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"name\": \"Copied Folder\"\n        },\n        {\n            \"type\": \"folder\",\n            \"id\": \"33333\",\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"name\": \"SDK Test Folder\"\n        },\n        {\n            \"type\": \"folder\",\n            \"id\": \"444445\",\n            \"sequence_id\": \"1\",\n            \"etag\": \"1\",\n            \"name\": \"Test Folder\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"55555\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"555550\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"Copied file.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"66666\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"666660\",\n                \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n            },\n            \"sequence_id\": \"9\",\n            \"etag\": \"9\",\n            \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n            \"name\": \"test file.txt\"\n        }\n    ],\n    \"order\": [\n        {\n            \"by\": \"type\",\n            \"direction\": \"ASC\"\n        },\n        {\n            \"by\": \"name\",\n            \"direction\": \"ASC\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/folders/get_folders_id_items_page_2_folder_download.json",
    "content": "{\n    \"entries\": [\n        {\n            \"type\": \"file\",\n            \"id\": \"101\",\n            \"etag\": \"1\",\n            \"name\": \"file 101.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"102\",\n            \"etag\": \"1\",\n            \"name\": \"file 102.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"103\",\n            \"etag\": \"1\",\n            \"name\": \"file 103.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"104\",\n            \"etag\": \"1\",\n            \"name\": \"file 104.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"105\",\n            \"etag\": \"1\",\n            \"name\": \"file 105.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"106\",\n            \"etag\": \"1\",\n            \"name\": \"file 106.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"107\",\n            \"etag\": \"1\",\n            \"name\": \"file 107.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"108\",\n            \"etag\": \"1\",\n            \"name\": \"file 108.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"109\",\n            \"etag\": \"1\",\n            \"name\": \"file 109.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"110\",\n            \"etag\": \"1\",\n            \"name\": \"file 110.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"111\",\n            \"etag\": \"1\",\n            \"name\": \"file 111.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"112\",\n            \"etag\": \"1\",\n            \"name\": \"file 112.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"113\",\n            \"etag\": \"1\",\n            \"name\": \"file 113.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"114\",\n            \"etag\": \"1\",\n            \"name\": \"file 114.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"115\",\n            \"etag\": \"1\",\n            \"name\": \"file 115.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"116\",\n            \"etag\": \"1\",\n            \"name\": \"file 116.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"117\",\n            \"etag\": \"1\",\n            \"name\": \"file 117.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"118\",\n            \"etag\": \"1\",\n            \"name\": \"file 118.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"119\",\n            \"etag\": \"1\",\n            \"name\": \"file 119.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"120\",\n            \"etag\": \"1\",\n            \"name\": \"file 120.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"121\",\n            \"etag\": \"1\",\n            \"name\": \"file 121.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"122\",\n            \"etag\": \"1\",\n            \"name\": \"file 122.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"123\",\n            \"etag\": \"1\",\n            \"name\": \"file 123.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"124\",\n            \"etag\": \"1\",\n            \"name\": \"file 124.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"125\",\n            \"etag\": \"1\",\n            \"name\": \"file 125.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"126\",\n            \"etag\": \"1\",\n            \"name\": \"file 126.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"127\",\n            \"etag\": \"1\",\n            \"name\": \"file 127.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"128\",\n            \"etag\": \"1\",\n            \"name\": \"file 128.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"129\",\n            \"etag\": \"1\",\n            \"name\": \"file 129.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"130\",\n            \"etag\": \"1\",\n            \"name\": \"file 130.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"131\",\n            \"etag\": \"1\",\n            \"name\": \"file 131.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"132\",\n            \"etag\": \"1\",\n            \"name\": \"file 132.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"133\",\n            \"etag\": \"1\",\n            \"name\": \"file 133.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"134\",\n            \"etag\": \"1\",\n            \"name\": \"file 134.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"135\",\n            \"etag\": \"1\",\n            \"name\": \"file 135.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"136\",\n            \"etag\": \"1\",\n            \"name\": \"file 136.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"137\",\n            \"etag\": \"1\",\n            \"name\": \"file 137.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"138\",\n            \"etag\": \"1\",\n            \"name\": \"file 138.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"139\",\n            \"etag\": \"1\",\n            \"name\": \"file 139.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"140\",\n            \"etag\": \"1\",\n            \"name\": \"file 140.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"141\",\n            \"etag\": \"1\",\n            \"name\": \"file 141.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"142\",\n            \"etag\": \"1\",\n            \"name\": \"file 142.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"143\",\n            \"etag\": \"1\",\n            \"name\": \"file 143.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"144\",\n            \"etag\": \"1\",\n            \"name\": \"file 144.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"145\",\n            \"etag\": \"1\",\n            \"name\": \"file 145.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"146\",\n            \"etag\": \"1\",\n            \"name\": \"file 146.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"147\",\n            \"etag\": \"1\",\n            \"name\": \"file 147.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"148\",\n            \"etag\": \"1\",\n            \"name\": \"file 148.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"149\",\n            \"etag\": \"1\",\n            \"name\": \"file 149.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"150\",\n            \"etag\": \"1\",\n            \"name\": \"file 150.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"151\",\n            \"etag\": \"1\",\n            \"name\": \"file 151.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"152\",\n            \"etag\": \"1\",\n            \"name\": \"file 152.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"153\",\n            \"etag\": \"1\",\n            \"name\": \"file 153.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"154\",\n            \"etag\": \"1\",\n            \"name\": \"file 154.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"155\",\n            \"etag\": \"1\",\n            \"name\": \"file 155.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"156\",\n            \"etag\": \"1\",\n            \"name\": \"file 156.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"157\",\n            \"etag\": \"1\",\n            \"name\": \"file 157.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"158\",\n            \"etag\": \"1\",\n            \"name\": \"file 158.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"159\",\n            \"etag\": \"1\",\n            \"name\": \"file 159.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"160\",\n            \"etag\": \"1\",\n            \"name\": \"file 160.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"161\",\n            \"etag\": \"1\",\n            \"name\": \"file 161.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"162\",\n            \"etag\": \"1\",\n            \"name\": \"file 162.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"163\",\n            \"etag\": \"1\",\n            \"name\": \"file 163.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"164\",\n            \"etag\": \"1\",\n            \"name\": \"file 164.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"165\",\n            \"etag\": \"1\",\n            \"name\": \"file 165.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"166\",\n            \"etag\": \"1\",\n            \"name\": \"file 166.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"167\",\n            \"etag\": \"1\",\n            \"name\": \"file 167.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"168\",\n            \"etag\": \"1\",\n            \"name\": \"file 168.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"169\",\n            \"etag\": \"1\",\n            \"name\": \"file 169.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"170\",\n            \"etag\": \"1\",\n            \"name\": \"file 170.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"171\",\n            \"etag\": \"1\",\n            \"name\": \"file 171.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"172\",\n            \"etag\": \"1\",\n            \"name\": \"file 172.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"173\",\n            \"etag\": \"1\",\n            \"name\": \"file 173.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"174\",\n            \"etag\": \"1\",\n            \"name\": \"file 174.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"175\",\n            \"etag\": \"1\",\n            \"name\": \"file 175.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"176\",\n            \"etag\": \"1\",\n            \"name\": \"file 176.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"177\",\n            \"etag\": \"1\",\n            \"name\": \"file 177.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"178\",\n            \"etag\": \"1\",\n            \"name\": \"file 178.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"179\",\n            \"etag\": \"1\",\n            \"name\": \"file 179.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"180\",\n            \"etag\": \"1\",\n            \"name\": \"file 180.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"181\",\n            \"etag\": \"1\",\n            \"name\": \"file 181.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"182\",\n            \"etag\": \"1\",\n            \"name\": \"file 182.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"183\",\n            \"etag\": \"1\",\n            \"name\": \"file 183.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"184\",\n            \"etag\": \"1\",\n            \"name\": \"file 184.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"185\",\n            \"etag\": \"1\",\n            \"name\": \"file 185.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"186\",\n            \"etag\": \"1\",\n            \"name\": \"file 186.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"187\",\n            \"etag\": \"1\",\n            \"name\": \"file 187.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"188\",\n            \"etag\": \"1\",\n            \"name\": \"file 188.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"189\",\n            \"etag\": \"1\",\n            \"name\": \"file 189.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"190\",\n            \"etag\": \"1\",\n            \"name\": \"file 190.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"191\",\n            \"etag\": \"1\",\n            \"name\": \"file 191.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"192\",\n            \"etag\": \"1\",\n            \"name\": \"file 192.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"193\",\n            \"etag\": \"1\",\n            \"name\": \"file 193.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"194\",\n            \"etag\": \"1\",\n            \"name\": \"file 194.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"195\",\n            \"etag\": \"1\",\n            \"name\": \"file 195.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"196\",\n            \"etag\": \"1\",\n            \"name\": \"file 196.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"197\",\n            \"etag\": \"1\",\n            \"name\": \"file 197.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"198\",\n            \"etag\": \"1\",\n            \"name\": \"file 198.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"199\",\n            \"etag\": \"1\",\n            \"name\": \"file 199.txt\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"200\",\n            \"etag\": \"1\",\n            \"name\": \"file 200.txt\"\n        }\n    ],\n    \"limit\": 100,\n    \"order\": [\n        {\n            \"by\": \"name\",\n            \"direction\": \"ASC\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/folders/get_folders_id_large_folder.json",
    "content": "{\n    \"type\": \"folder\",\n    \"id\": \"11111\",\n    \"sequence_id\": \"0\",\n    \"etag\": \"0\",\n    \"name\": \"DownloadFolderTest\",\n    \"created_at\": \"2018-09-19T09:20:37-07:00\",\n    \"modified_at\": \"2018-09-19T09:20:37-07:00\",\n    \"description\": \"\",\n    \"size\": 8183737,\n    \"path_collection\": {\n        \"total_count\": 1,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"name\": \"All Files\"\n            }\n        ]\n    },\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": null,\n    \"content_modified_at\": null,\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"shared_link\": null,\n    \"folder_upload_email\": null,\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"0\",\n        \"name\": \"All Files\"\n    },\n    \"item_status\": \"active\",\n    \"item_collection\": {\n        \"total_count\": 200,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"22222\",\n                \"sequence_id\": \"1\",\n                \"etag\": \"1\",\n                \"name\": \"subfolder\"\n            },\n            {\n                \"type\": \"file\",\n                \"id\": \"44444\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"444441\",\n                    \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n                },\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n                \"name\": \"file 1.txt\"\n            },\n            {\n                \"type\": \"file\",\n                \"id\": \"55555\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"555551\",\n                    \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n                },\n                \"sequence_id\": \"9\",\n                \"etag\": \"9\",\n                \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n                \"name\": \"file 2.txt\"\n            }\n        ],\n        \"offset\": 0,\n        \"limit\": 3,\n        \"order\": [\n            {\n                \"by\": \"type\",\n                \"direction\": \"ASC\"\n            },\n            {\n                \"by\": \"name\",\n                \"direction\": \"ASC\"\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": "test/fixtures/folders/get_folders_id_metadata.json",
    "content": "{\n    \"entries\": [\n        {\n            \"$type\": \"testTemplate-2890e928-874d-4959-afb7-6a778b3ad75c\",\n            \"$parent\": \"folder_11111\",\n            \"$id\": \"ff8cb88e-de80-467c-aa02-412c1cdaee48\",\n            \"$version\": 1,\n            \"$typeVersion\": 0,\n            \"testEnum\": \"foo\",\n            \"$template\": \"testTemplate\",\n            \"$scope\": \"enterprise_22222\"\n        }\n    ],\n    \"limit\": 100\n}\n"
  },
  {
    "path": "test/fixtures/folders/get_folders_id_metadata_scope_template.json",
    "content": "{\n    \"$type\": \"testTemplate-2890e938-874d-4059-afc7-6a778b3ad75c\",\n    \"$parent\": \"folder_11111\",\n    \"$id\": \"ff8ab88e-de80-567c-aa02-412c1cdaee36\",\n    \"$version\": 1,\n    \"$typeVersion\": 0,\n    \"testEnum\": \"foo\",\n    \"$template\": \"testTemplate\",\n    \"$scope\": \"enterprise_22222\"\n}\n"
  },
  {
    "path": "test/fixtures/folders/get_folders_id_subfolder_download.json",
    "content": "{\n    \"type\": \"folder\",\n    \"id\": \"22222\",\n    \"sequence_id\": \"1\",\n    \"etag\": \"1\",\n    \"name\": \"subfolder\",\n    \"created_at\": \"2018-09-19T09:20:37-07:00\",\n    \"modified_at\": \"2018-09-19T09:20:37-07:00\",\n    \"description\": \"\",\n    \"size\": 8183737,\n    \"path_collection\": {\n        \"total_count\": 1,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"name\": \"All Files\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"11111\",\n                \"name\": \"DownloadFolderTest\"\n            }\n        ]\n    },\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": null,\n    \"content_modified_at\": null,\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"shared_link\": null,\n    \"folder_upload_email\": null,\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"11111\",\n        \"name\": \"DownloadFolderTest\"\n    },\n    \"item_status\": \"active\",\n    \"item_collection\": {\n        \"total_count\": 1,\n        \"entries\": [\n            {\n                \"type\": \"file\",\n                \"id\": \"77777\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"777771\",\n                    \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n                },\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n                \"name\": \"subfolder file 1.txt\"\n            }\n        ],\n        \"offset\": 0,\n        \"limit\": 100,\n        \"order\": [\n            {\n                \"by\": \"type\",\n                \"direction\": \"ASC\"\n            },\n            {\n                \"by\": \"name\",\n                \"direction\": \"ASC\"\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": "test/fixtures/folders/post_collaborations_user.json",
    "content": "{\n    \"type\": \"collaboration\",\n    \"id\": \"1234567890\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"9753108642\",\n        \"name\": \"Inviting User\",\n        \"login\": \"invites@example.com\"\n    },\n    \"created_at\": \"2016-11-16T21:33:31-08:00\",\n    \"modified_at\": \"2016-11-16T21:33:31-08:00\",\n    \"expires_at\": null,\n    \"status\": \"accepted\",\n    \"accessible_by\": {\n        \"type\": \"user\",\n        \"id\": \"987654321\",\n        \"name\": \"My New Friend\",\n        \"login\": \"newfriend@example.com\"\n    },\n    \"role\": \"previewer\",\n    \"acknowledged_at\": \"2016-11-16T21:33:31-08:00\",\n    \"item\": {\n        \"type\": \"folder\",\n        \"id\": \"0\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"Collaborated Folder\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/folders/post_files_content.json",
    "content": "{\n    \"total_count\":1,\n    \"entries\":[\n        {\n            \"type\":\"file\",\n            \"id\":\"1234567890\",\n            \"file_version\":{\n                \"type\":\"file_version\",\n                \"id\":\"098765432109\",\n                \"sha1\":\"0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33\"\n            },\n            \"sequence_id\":\"0\",\n            \"etag\":\"0\",\n            \"sha1\":\"0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33\",\n            \"name\":\"file.txt\",\n            \"description\":\"\",\n            \"size\":3,\n            \"path_collection\":{\n                \"total_count\":1,\n                \"entries\":[\n                    {\n                        \"type\":\"folder\",\n                        \"id\":\"0\",\n                        \"sequence_id\":null,\n                        \"etag\":null,\n                        \"name\":\"All Files\"\n                    }\n                ]\n            },\n            \"created_at\":\"2017-05-16T15:18:02-07:00\",\n            \"modified_at\":\"2017-05-16T15:18:02-07:00\",\n            \"trashed_at\":null,\n            \"purged_at\":null,\n            \"content_created_at\":\"2017-05-16T15:18:02-07:00\",\n            \"content_modified_at\":\"2017-05-16T15:18:02-07:00\",\n            \"created_by\":{\n                \"type\":\"user\",\n                \"id\":\"123456789\",\n                \"name\":\"Test User\",\n                \"login\":\"test@example.com\"\n            },\n            \"modified_by\":{\n                \"type\":\"user\",\n                \"id\":\"123456789\",\n                \"name\":\"Test User\",\n                \"login\":\"test@example.com\"\n            },\n            \"owned_by\":{\n                \"type\":\"user\",\n                \"id\":\"182069272\",\n                \"name\":\"Matt Willer\",\n                \"login\":\"mwiller@example.com\"\n            },\n            \"shared_link\":null,\n            \"parent\":{\n                \"type\":\"user\",\n                \"id\":\"123456789\",\n                \"name\":\"Test User\",\n                \"login\":\"test@example.com\"\n            },\n            \"item_status\":\"active\"\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/folders/post_folder_locks.json",
    "content": "{\n    \"id\": \"12345678\",\n    \"type\": \"folder_lock\",\n    \"created_at\": \"2020-09-14T23:12:53Z\",\n    \"created_by\": {\n        \"id\": \"11446498\",\n        \"type\": \"user\"\n    },\n    \"folder\": {\n        \"id\": \"12345\",\n        \"type\": \"folder\",\n        \"etag\": \"1\",\n        \"name\": \"Contracts\",\n        \"sequence_id\": \"3\"\n    },\n    \"lock_type\": \"freeze\",\n    \"locked_operations\": {\n        \"delete\": true,\n        \"move\": true\n    }\n}\n"
  },
  {
    "path": "test/fixtures/folders/post_folders.json",
    "content": "{\n    \"type\": \"folder\",\n    \"id\": \"22222\",\n    \"sequence_id\": \"0\",\n    \"etag\": \"0\",\n    \"name\": \"New Folder\",\n    \"created_at\": \"2018-04-25T13:11:51-07:00\",\n    \"modified_at\": \"2018-04-25T13:11:51-07:00\",\n    \"description\": \"\",\n    \"size\": 0,\n    \"path_collection\": {\n        \"total_count\": 1,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            }\n        ]\n    },\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": \"2018-04-25T13:11:51-07:00\",\n    \"content_modified_at\": \"2018-04-25T13:11:51-07:00\",\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"shared_link\": null,\n    \"folder_upload_email\": null,\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"0\",\n        \"sequence_id\": null,\n        \"etag\": null,\n        \"name\": \"All Files\"\n    },\n    \"item_status\": \"active\",\n    \"item_collection\": {\n        \"total_count\": 0,\n        \"entries\": [],\n        \"offset\": 0,\n        \"limit\": 100,\n        \"order\": [\n            {\n                \"by\": \"type\",\n                \"direction\": \"ASC\"\n            },\n            {\n                \"by\": \"name\",\n                \"direction\": \"ASC\"\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": "test/fixtures/folders/post_folders_id_copy.json",
    "content": "{\n    \"type\": \"folder\",\n    \"id\": \"0\",\n    \"sequence_id\": \"0\",\n    \"etag\": \"0\",\n    \"name\": \"New Folder (1)\",\n    \"created_at\": \"2018-04-25T13:18:21-07:00\",\n    \"modified_at\": \"2018-04-25T13:18:21-07:00\",\n    \"description\": \"\",\n    \"size\": 0,\n    \"path_collection\": {\n        \"total_count\": 1,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            }\n        ]\n    },\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": \"2018-04-25T13:18:21-07:00\",\n    \"content_modified_at\": \"2018-04-25T13:18:21-07:00\",\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"shared_link\": null,\n    \"folder_upload_email\": null,\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"987654321\",\n        \"sequence_id\": null,\n        \"etag\": null,\n        \"name\": \"All Files\"\n    },\n    \"item_status\": \"active\",\n    \"item_collection\": {\n        \"total_count\": 0,\n        \"entries\": [],\n        \"offset\": 0,\n        \"limit\": 100,\n        \"order\": [\n            {\n                \"by\": \"type\",\n                \"direction\": \"ASC\"\n            },\n            {\n                \"by\": \"name\",\n                \"direction\": \"ASC\"\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": "test/fixtures/folders/post_folders_id_metadata_scope_template.json",
    "content": "{\n    \"$type\": \"testTemplate-2890e938-874d-4059-afc7-6a778b3ad75c\",\n    \"$parent\": \"folder_11111\",\n    \"$id\": \"ff8ab88e-de80-567c-aa02-412c1cdaee36\",\n    \"$version\": 1,\n    \"$typeVersion\": 0,\n    \"testEnum\": \"foo\",\n    \"$template\": \"testTemplate\",\n    \"$scope\": \"enterprise_22222\"\n}\n"
  },
  {
    "path": "test/fixtures/folders/put_collaborations_id.json",
    "content": "{\n    \"type\": \"collaboration\",\n    \"id\": \"1234567890\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"834098476\",\n        \"name\": \"Inviting User\",\n        \"login\": \"inviter@example.com\"\n    },\n    \"created_at\": \"2015-11-03T18:36:37-08:00\",\n    \"modified_at\": \"2016-11-16T21:01:19-08:00\",\n    \"expires_at\": null,\n    \"status\": \"accepted\",\n    \"accessible_by\": {\n        \"type\": \"user\",\n        \"id\": \"6789234576\",\n        \"name\": \"Collaborated User\",\n        \"login\": \"collaborator@example.com\"\n    },\n    \"role\": \"viewer uploader\",\n    \"acknowledged_at\": \"2015-11-03T18:36:37-08:00\",\n    \"item\": {\n        \"type\": \"folder\",\n        \"id\": \"9087654321\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"name\": \"Collaborated Folder\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/folders/put_folders_id.json",
    "content": "{\n    \"type\": \"folder\",\n    \"id\": \"0\",\n    \"sequence_id\": \"1\",\n    \"etag\": \"1\",\n    \"name\": \"New Folder Name\",\n    \"created_at\": \"2018-04-25T13:11:51-07:00\",\n    \"modified_at\": \"2018-04-25T14:06:20-07:00\",\n    \"description\": \"My new folder\",\n    \"size\": 0,\n    \"path_collection\": {\n        \"total_count\": 1,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            }\n        ]\n    },\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": \"2018-04-25T13:11:51-07:00\",\n    \"content_modified_at\": \"2018-04-25T14:06:20-07:00\",\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"shared_link\": null,\n    \"folder_upload_email\": null,\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"987654321\",\n        \"sequence_id\": null,\n        \"etag\": null,\n        \"name\": \"All Files\"\n    },\n    \"item_status\": \"active\",\n    \"item_collection\": {\n        \"total_count\": 0,\n        \"entries\": [],\n        \"offset\": 0,\n        \"limit\": 100,\n        \"order\": [\n            {\n                \"by\": \"type\",\n                \"direction\": \"ASC\"\n            },\n            {\n                \"by\": \"name\",\n                \"direction\": \"ASC\"\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": "test/fixtures/folders/put_folders_id_shared_link.json",
    "content": "{\n    \"type\": \"folder\",\n    \"id\": \"0\",\n    \"shared_link\": {\n        \"url\": \"https://blosserdemoaccount.box.com/s/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p\",\n        \"download_url\": \"https://blosserdemoaccount.box.com/shared/static/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p.png\",\n        \"vanity_url\": \"https://app.box.com/v/my-custom-name-123\",\n        \"effective_access\": \"open\",\n        \"is_password_enabled\": true,\n        \"unshared_at\": null,\n        \"download_count\": 0,\n        \"preview_count\": 0,\n        \"access\": \"test\",\n        \"permissions\": {\n            \"can_download\": true,\n            \"can_preview\": true\n        }\n    }\n}\n"
  },
  {
    "path": "test/fixtures/folders/test_folder/nested_folder/test_file.txt",
    "content": ""
  },
  {
    "path": "test/fixtures/folders/test_folder/test_file.txt",
    "content": "hello"
  },
  {
    "path": "test/fixtures/github/releases-v4.4.1.json",
    "content": "[\n    {\n      \"url\": \"https://api.github.com/repos/box/boxcli/releases/256056113\",\n      \"assets_url\": \"https://api.github.com/repos/box/boxcli/releases/256056113/assets\",\n      \"upload_url\": \"https://uploads.github.com/repos/box/boxcli/releases/256056113/assets{?name,label}\",\n      \"html_url\": \"https://github.com/box/boxcli/releases/tag/v4.4.1\",\n      \"id\": 256056113,\n      \"author\": {\n        \"login\": \"box-sdk-build\",\n        \"id\": 94016436,\n        \"node_id\": \"U_kgDOBZqTtA\",\n        \"avatar_url\": \"https://avatars.githubusercontent.com/u/94016436?v=4\",\n        \"gravatar_id\": \"\",\n        \"url\": \"https://api.github.com/users/box-sdk-build\",\n        \"html_url\": \"https://github.com/box-sdk-build\",\n        \"followers_url\": \"https://api.github.com/users/box-sdk-build/followers\",\n        \"following_url\": \"https://api.github.com/users/box-sdk-build/following{/other_user}\",\n        \"gists_url\": \"https://api.github.com/users/box-sdk-build/gists{/gist_id}\",\n        \"starred_url\": \"https://api.github.com/users/box-sdk-build/starred{/owner}{/repo}\",\n        \"subscriptions_url\": \"https://api.github.com/users/box-sdk-build/subscriptions\",\n        \"organizations_url\": \"https://api.github.com/users/box-sdk-build/orgs\",\n        \"repos_url\": \"https://api.github.com/users/box-sdk-build/repos\",\n        \"events_url\": \"https://api.github.com/users/box-sdk-build/events{/privacy}\",\n        \"received_events_url\": \"https://api.github.com/users/box-sdk-build/received_events\",\n        \"type\": \"User\",\n        \"user_view_type\": \"public\",\n        \"site_admin\": false\n      },\n      \"node_id\": \"RE_kwDOBZPwVs4PQxsx\",\n      \"tag_name\": \"v4.4.1\",\n      \"target_commitish\": \"main\",\n      \"name\": \"v4.4.1\",\n      \"draft\": false,\n      \"immutable\": false,\n      \"prerelease\": false,\n      \"created_at\": \"2025-10-21T15:28:56Z\",\n      \"updated_at\": \"2025-10-30T13:45:30Z\",\n      \"published_at\": \"2025-10-21T16:06:08Z\",\n      \"assets\": [\n        {\n          \"url\": \"https://api.github.com/repos/box/boxcli/releases/assets/306955038\",\n          \"id\": 306955038,\n          \"node_id\": \"RA_kwDOBZPwVs4SS8Me\",\n          \"name\": \"box-v4.4.1-arm64.exe\",\n          \"label\": null,\n          \"uploader\": {\n            \"login\": \"arjankowski\",\n            \"id\": 90028884,\n            \"node_id\": \"MDQ6VXNlcjkwMDI4ODg0\",\n            \"avatar_url\": \"https://avatars.githubusercontent.com/u/90028884?v=4\",\n            \"gravatar_id\": \"\",\n            \"url\": \"https://api.github.com/users/arjankowski\",\n            \"html_url\": \"https://github.com/arjankowski\",\n            \"followers_url\": \"https://api.github.com/users/arjankowski/followers\",\n            \"following_url\": \"https://api.github.com/users/arjankowski/following{/other_user}\",\n            \"gists_url\": \"https://api.github.com/users/arjankowski/gists{/gist_id}\",\n            \"starred_url\": \"https://api.github.com/users/arjankowski/starred{/owner}{/repo}\",\n            \"subscriptions_url\": \"https://api.github.com/users/arjankowski/subscriptions\",\n            \"organizations_url\": \"https://api.github.com/users/arjankowski/orgs\",\n            \"repos_url\": \"https://api.github.com/users/arjankowski/repos\",\n            \"events_url\": \"https://api.github.com/users/arjankowski/events{/privacy}\",\n            \"received_events_url\": \"https://api.github.com/users/arjankowski/received_events\",\n            \"type\": \"User\",\n            \"user_view_type\": \"public\",\n            \"site_admin\": false\n          },\n          \"content_type\": \"application/x-msdownload\",\n          \"state\": \"uploaded\",\n          \"size\": 40864608,\n          \"digest\": \"sha256:2799640c53967e76bd18bdbfadf46913715bfaeecd83d8c484617780e0946d07\",\n          \"download_count\": 70,\n          \"created_at\": \"2025-10-21T16:05:30Z\",\n          \"updated_at\": \"2025-10-21T16:05:32Z\",\n          \"browser_download_url\": \"https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-arm64.exe\"\n        },\n        {\n          \"url\": \"https://api.github.com/repos/box/boxcli/releases/assets/306955017\",\n          \"id\": 306955017,\n          \"node_id\": \"RA_kwDOBZPwVs4SS8MJ\",\n          \"name\": \"box-v4.4.1-arm64.pkg\",\n          \"label\": null,\n          \"uploader\": {\n            \"login\": \"arjankowski\",\n            \"id\": 90028884,\n            \"node_id\": \"MDQ6VXNlcjkwMDI4ODg0\",\n            \"avatar_url\": \"https://avatars.githubusercontent.com/u/90028884?v=4\",\n            \"gravatar_id\": \"\",\n            \"url\": \"https://api.github.com/users/arjankowski\",\n            \"html_url\": \"https://github.com/arjankowski\",\n            \"followers_url\": \"https://api.github.com/users/arjankowski/followers\",\n            \"following_url\": \"https://api.github.com/users/arjankowski/following{/other_user}\",\n            \"gists_url\": \"https://api.github.com/users/arjankowski/gists{/gist_id}\",\n            \"starred_url\": \"https://api.github.com/users/arjankowski/starred{/owner}{/repo}\",\n            \"subscriptions_url\": \"https://api.github.com/users/arjankowski/subscriptions\",\n            \"organizations_url\": \"https://api.github.com/users/arjankowski/orgs\",\n            \"repos_url\": \"https://api.github.com/users/arjankowski/repos\",\n            \"events_url\": \"https://api.github.com/users/arjankowski/events{/privacy}\",\n            \"received_events_url\": \"https://api.github.com/users/arjankowski/received_events\",\n            \"type\": \"User\",\n            \"user_view_type\": \"public\",\n            \"site_admin\": false\n          },\n          \"content_type\": \"application/octet-stream\",\n          \"state\": \"uploaded\",\n          \"size\": 45976397,\n          \"digest\": \"sha256:0bbddca6716900056914f4bac94827e381ab68a353bb2acab86fe63bf2ac0c43\",\n          \"download_count\": 64,\n          \"created_at\": \"2025-10-21T16:05:20Z\",\n          \"updated_at\": \"2025-10-21T16:05:23Z\",\n          \"browser_download_url\": \"https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-arm64.pkg\"\n        },\n        {\n          \"url\": \"https://api.github.com/repos/box/boxcli/releases/assets/310533045\",\n          \"id\": 310533045,\n          \"node_id\": \"RA_kwDOBZPwVs4Sglu1\",\n          \"name\": \"box-v4.4.1-darwin-arm64.tar.gz\",\n          \"label\": null,\n          \"uploader\": {\n            \"login\": \"congminh1254\",\n            \"id\": 9329079,\n            \"node_id\": \"MDQ6VXNlcjkzMjkwNzk=\",\n            \"avatar_url\": \"https://avatars.githubusercontent.com/u/9329079?v=4\",\n            \"gravatar_id\": \"\",\n            \"url\": \"https://api.github.com/users/congminh1254\",\n            \"html_url\": \"https://github.com/congminh1254\",\n            \"followers_url\": \"https://api.github.com/users/congminh1254/followers\",\n            \"following_url\": \"https://api.github.com/users/congminh1254/following{/other_user}\",\n            \"gists_url\": \"https://api.github.com/users/congminh1254/gists{/gist_id}\",\n            \"starred_url\": \"https://api.github.com/users/congminh1254/starred{/owner}{/repo}\",\n            \"subscriptions_url\": \"https://api.github.com/users/congminh1254/subscriptions\",\n            \"organizations_url\": \"https://api.github.com/users/congminh1254/orgs\",\n            \"repos_url\": \"https://api.github.com/users/congminh1254/repos\",\n            \"events_url\": \"https://api.github.com/users/congminh1254/events{/privacy}\",\n            \"received_events_url\": \"https://api.github.com/users/congminh1254/received_events\",\n            \"type\": \"User\",\n            \"user_view_type\": \"public\",\n            \"site_admin\": false\n          },\n          \"content_type\": \"application/x-gzip\",\n          \"state\": \"uploaded\",\n          \"size\": 46259951,\n          \"digest\": \"sha256:716923f5a7c32f5344662eb10e2f10f9d89fb008e1d418b99cbcbe4247c1bc6f\",\n          \"download_count\": 10,\n          \"created_at\": \"2025-10-30T13:45:10Z\",\n          \"updated_at\": \"2025-10-30T13:45:13Z\",\n          \"browser_download_url\": \"https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-darwin-arm64.tar.gz\"\n        },\n        {\n          \"url\": \"https://api.github.com/repos/box/boxcli/releases/assets/310533093\",\n          \"id\": 310533093,\n          \"node_id\": \"RA_kwDOBZPwVs4Sglvl\",\n          \"name\": \"box-v4.4.1-darwin-x64.tar.gz\",\n          \"label\": null,\n          \"uploader\": {\n            \"login\": \"congminh1254\",\n            \"id\": 9329079,\n            \"node_id\": \"MDQ6VXNlcjkzMjkwNzk=\",\n            \"avatar_url\": \"https://avatars.githubusercontent.com/u/9329079?v=4\",\n            \"gravatar_id\": \"\",\n            \"url\": \"https://api.github.com/users/congminh1254\",\n            \"html_url\": \"https://github.com/congminh1254\",\n            \"followers_url\": \"https://api.github.com/users/congminh1254/followers\",\n            \"following_url\": \"https://api.github.com/users/congminh1254/following{/other_user}\",\n            \"gists_url\": \"https://api.github.com/users/congminh1254/gists{/gist_id}\",\n            \"starred_url\": \"https://api.github.com/users/congminh1254/starred{/owner}{/repo}\",\n            \"subscriptions_url\": \"https://api.github.com/users/congminh1254/subscriptions\",\n            \"organizations_url\": \"https://api.github.com/users/congminh1254/orgs\",\n            \"repos_url\": \"https://api.github.com/users/congminh1254/repos\",\n            \"events_url\": \"https://api.github.com/users/congminh1254/events{/privacy}\",\n            \"received_events_url\": \"https://api.github.com/users/congminh1254/received_events\",\n            \"type\": \"User\",\n            \"user_view_type\": \"public\",\n            \"site_admin\": false\n          },\n          \"content_type\": \"application/x-gzip\",\n          \"state\": \"uploaded\",\n          \"size\": 47572645,\n          \"digest\": \"sha256:8dac71613287363ffca3dcb7d84805142cb4d10878f03b4fcda3916d660138d2\",\n          \"download_count\": 2,\n          \"created_at\": \"2025-10-30T13:45:13Z\",\n          \"updated_at\": \"2025-10-30T13:45:17Z\",\n          \"browser_download_url\": \"https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-darwin-x64.tar.gz\"\n        },\n        {\n          \"url\": \"https://api.github.com/repos/box/boxcli/releases/assets/310533126\",\n          \"id\": 310533126,\n          \"node_id\": \"RA_kwDOBZPwVs4SglwG\",\n          \"name\": \"box-v4.4.1-win32-arm64.tar.gz\",\n          \"label\": null,\n          \"uploader\": {\n            \"login\": \"congminh1254\",\n            \"id\": 9329079,\n            \"node_id\": \"MDQ6VXNlcjkzMjkwNzk=\",\n            \"avatar_url\": \"https://avatars.githubusercontent.com/u/9329079?v=4\",\n            \"gravatar_id\": \"\",\n            \"url\": \"https://api.github.com/users/congminh1254\",\n            \"html_url\": \"https://github.com/congminh1254\",\n            \"followers_url\": \"https://api.github.com/users/congminh1254/followers\",\n            \"following_url\": \"https://api.github.com/users/congminh1254/following{/other_user}\",\n            \"gists_url\": \"https://api.github.com/users/congminh1254/gists{/gist_id}\",\n            \"starred_url\": \"https://api.github.com/users/congminh1254/starred{/owner}{/repo}\",\n            \"subscriptions_url\": \"https://api.github.com/users/congminh1254/subscriptions\",\n            \"organizations_url\": \"https://api.github.com/users/congminh1254/orgs\",\n            \"repos_url\": \"https://api.github.com/users/congminh1254/repos\",\n            \"events_url\": \"https://api.github.com/users/congminh1254/events{/privacy}\",\n            \"received_events_url\": \"https://api.github.com/users/congminh1254/received_events\",\n            \"type\": \"User\",\n            \"user_view_type\": \"public\",\n            \"site_admin\": false\n          },\n          \"content_type\": \"application/x-gzip\",\n          \"state\": \"uploaded\",\n          \"size\": 40294369,\n          \"digest\": \"sha256:52b3e75426d0de2b0c4343e36ae125f1124cc748899675681957f0770647f301\",\n          \"download_count\": 2,\n          \"created_at\": \"2025-10-30T13:45:17Z\",\n          \"updated_at\": \"2025-10-30T13:45:20Z\",\n          \"browser_download_url\": \"https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-win32-arm64.tar.gz\"\n        },\n        {\n          \"url\": \"https://api.github.com/repos/box/boxcli/releases/assets/310533136\",\n          \"id\": 310533136,\n          \"node_id\": \"RA_kwDOBZPwVs4SglwQ\",\n          \"name\": \"box-v4.4.1-win32-x64.tar.gz\",\n          \"label\": null,\n          \"uploader\": {\n            \"login\": \"congminh1254\",\n            \"id\": 9329079,\n            \"node_id\": \"MDQ6VXNlcjkzMjkwNzk=\",\n            \"avatar_url\": \"https://avatars.githubusercontent.com/u/9329079?v=4\",\n            \"gravatar_id\": \"\",\n            \"url\": \"https://api.github.com/users/congminh1254\",\n            \"html_url\": \"https://github.com/congminh1254\",\n            \"followers_url\": \"https://api.github.com/users/congminh1254/followers\",\n            \"following_url\": \"https://api.github.com/users/congminh1254/following{/other_user}\",\n            \"gists_url\": \"https://api.github.com/users/congminh1254/gists{/gist_id}\",\n            \"starred_url\": \"https://api.github.com/users/congminh1254/starred{/owner}{/repo}\",\n            \"subscriptions_url\": \"https://api.github.com/users/congminh1254/subscriptions\",\n            \"organizations_url\": \"https://api.github.com/users/congminh1254/orgs\",\n            \"repos_url\": \"https://api.github.com/users/congminh1254/repos\",\n            \"events_url\": \"https://api.github.com/users/congminh1254/events{/privacy}\",\n            \"received_events_url\": \"https://api.github.com/users/congminh1254/received_events\",\n            \"type\": \"User\",\n            \"user_view_type\": \"public\",\n            \"site_admin\": false\n          },\n          \"content_type\": \"application/x-gzip\",\n          \"state\": \"uploaded\",\n          \"size\": 43831921,\n          \"digest\": \"sha256:6c513c3abcf55f15f938e5040ca44ec73a46c65142cb212aea0667f62a63244f\",\n          \"download_count\": 12,\n          \"created_at\": \"2025-10-30T13:45:20Z\",\n          \"updated_at\": \"2025-10-30T13:45:25Z\",\n          \"browser_download_url\": \"https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-win32-x64.tar.gz\"\n        },\n        {\n          \"url\": \"https://api.github.com/repos/box/boxcli/releases/assets/310533149\",\n          \"id\": 310533149,\n          \"node_id\": \"RA_kwDOBZPwVs4Sglwd\",\n          \"name\": \"box-v4.4.1-win32-x86.tar.gz\",\n          \"label\": null,\n          \"uploader\": {\n            \"login\": \"congminh1254\",\n            \"id\": 9329079,\n            \"node_id\": \"MDQ6VXNlcjkzMjkwNzk=\",\n            \"avatar_url\": \"https://avatars.githubusercontent.com/u/9329079?v=4\",\n            \"gravatar_id\": \"\",\n            \"url\": \"https://api.github.com/users/congminh1254\",\n            \"html_url\": \"https://github.com/congminh1254\",\n            \"followers_url\": \"https://api.github.com/users/congminh1254/followers\",\n            \"following_url\": \"https://api.github.com/users/congminh1254/following{/other_user}\",\n            \"gists_url\": \"https://api.github.com/users/congminh1254/gists{/gist_id}\",\n            \"starred_url\": \"https://api.github.com/users/congminh1254/starred{/owner}{/repo}\",\n            \"subscriptions_url\": \"https://api.github.com/users/congminh1254/subscriptions\",\n            \"organizations_url\": \"https://api.github.com/users/congminh1254/orgs\",\n            \"repos_url\": \"https://api.github.com/users/congminh1254/repos\",\n            \"events_url\": \"https://api.github.com/users/congminh1254/events{/privacy}\",\n            \"received_events_url\": \"https://api.github.com/users/congminh1254/received_events\",\n            \"type\": \"User\",\n            \"user_view_type\": \"public\",\n            \"site_admin\": false\n          },\n          \"content_type\": \"application/x-gzip\",\n          \"state\": \"uploaded\",\n          \"size\": 41666897,\n          \"digest\": \"sha256:49b1fb986d488d5608ea1f4d8050f59d7d51a4f7d24d8be45bc7d8619ce463b6\",\n          \"download_count\": 1,\n          \"created_at\": \"2025-10-30T13:45:25Z\",\n          \"updated_at\": \"2025-10-30T13:45:30Z\",\n          \"browser_download_url\": \"https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-win32-x86.tar.gz\"\n        },\n        {\n          \"url\": \"https://api.github.com/repos/box/boxcli/releases/assets/306954997\",\n          \"id\": 306954997,\n          \"node_id\": \"RA_kwDOBZPwVs4SS8L1\",\n          \"name\": \"box-v4.4.1-x64.exe\",\n          \"label\": null,\n          \"uploader\": {\n            \"login\": \"arjankowski\",\n            \"id\": 90028884,\n            \"node_id\": \"MDQ6VXNlcjkwMDI4ODg0\",\n            \"avatar_url\": \"https://avatars.githubusercontent.com/u/90028884?v=4\",\n            \"gravatar_id\": \"\",\n            \"url\": \"https://api.github.com/users/arjankowski\",\n            \"html_url\": \"https://github.com/arjankowski\",\n            \"followers_url\": \"https://api.github.com/users/arjankowski/followers\",\n            \"following_url\": \"https://api.github.com/users/arjankowski/following{/other_user}\",\n            \"gists_url\": \"https://api.github.com/users/arjankowski/gists{/gist_id}\",\n            \"starred_url\": \"https://api.github.com/users/arjankowski/starred{/owner}{/repo}\",\n            \"subscriptions_url\": \"https://api.github.com/users/arjankowski/subscriptions\",\n            \"organizations_url\": \"https://api.github.com/users/arjankowski/orgs\",\n            \"repos_url\": \"https://api.github.com/users/arjankowski/repos\",\n            \"events_url\": \"https://api.github.com/users/arjankowski/events{/privacy}\",\n            \"received_events_url\": \"https://api.github.com/users/arjankowski/received_events\",\n            \"type\": \"User\",\n            \"user_view_type\": \"public\",\n            \"site_admin\": false\n          },\n          \"content_type\": \"application/x-msdownload\",\n          \"state\": \"uploaded\",\n          \"size\": 44371656,\n          \"digest\": \"sha256:ad2842018983aa45e44ad865077c289538c7bdf62dbbabfc37d6ce300cb1e0ed\",\n          \"download_count\": 454,\n          \"created_at\": \"2025-10-21T16:05:13Z\",\n          \"updated_at\": \"2025-10-21T16:05:16Z\",\n          \"browser_download_url\": \"https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-x64.exe\"\n        },\n        {\n          \"url\": \"https://api.github.com/repos/box/boxcli/releases/assets/306954968\",\n          \"id\": 306954968,\n          \"node_id\": \"RA_kwDOBZPwVs4SS8LY\",\n          \"name\": \"box-v4.4.1-x64.pkg\",\n          \"label\": null,\n          \"uploader\": {\n            \"login\": \"arjankowski\",\n            \"id\": 90028884,\n            \"node_id\": \"MDQ6VXNlcjkwMDI4ODg0\",\n            \"avatar_url\": \"https://avatars.githubusercontent.com/u/90028884?v=4\",\n            \"gravatar_id\": \"\",\n            \"url\": \"https://api.github.com/users/arjankowski\",\n            \"html_url\": \"https://github.com/arjankowski\",\n            \"followers_url\": \"https://api.github.com/users/arjankowski/followers\",\n            \"following_url\": \"https://api.github.com/users/arjankowski/following{/other_user}\",\n            \"gists_url\": \"https://api.github.com/users/arjankowski/gists{/gist_id}\",\n            \"starred_url\": \"https://api.github.com/users/arjankowski/starred{/owner}{/repo}\",\n            \"subscriptions_url\": \"https://api.github.com/users/arjankowski/subscriptions\",\n            \"organizations_url\": \"https://api.github.com/users/arjankowski/orgs\",\n            \"repos_url\": \"https://api.github.com/users/arjankowski/repos\",\n            \"events_url\": \"https://api.github.com/users/arjankowski/events{/privacy}\",\n            \"received_events_url\": \"https://api.github.com/users/arjankowski/received_events\",\n            \"type\": \"User\",\n            \"user_view_type\": \"public\",\n            \"site_admin\": false\n          },\n          \"content_type\": \"application/octet-stream\",\n          \"state\": \"uploaded\",\n          \"size\": 47657267,\n          \"digest\": \"sha256:4b9f779b97910763c80fa4ad8035de6b8e6a04666a2561e703eb0519727da8ce\",\n          \"download_count\": 15,\n          \"created_at\": \"2025-10-21T16:05:07Z\",\n          \"updated_at\": \"2025-10-21T16:05:11Z\",\n          \"browser_download_url\": \"https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-x64.pkg\"\n        },\n        {\n          \"url\": \"https://api.github.com/repos/box/boxcli/releases/assets/306954923\",\n          \"id\": 306954923,\n          \"node_id\": \"RA_kwDOBZPwVs4SS8Kr\",\n          \"name\": \"box-v4.4.1-x86.exe\",\n          \"label\": null,\n          \"uploader\": {\n            \"login\": \"arjankowski\",\n            \"id\": 90028884,\n            \"node_id\": \"MDQ6VXNlcjkwMDI4ODg0\",\n            \"avatar_url\": \"https://avatars.githubusercontent.com/u/90028884?v=4\",\n            \"gravatar_id\": \"\",\n            \"url\": \"https://api.github.com/users/arjankowski\",\n            \"html_url\": \"https://github.com/arjankowski\",\n            \"followers_url\": \"https://api.github.com/users/arjankowski/followers\",\n            \"following_url\": \"https://api.github.com/users/arjankowski/following{/other_user}\",\n            \"gists_url\": \"https://api.github.com/users/arjankowski/gists{/gist_id}\",\n            \"starred_url\": \"https://api.github.com/users/arjankowski/starred{/owner}{/repo}\",\n            \"subscriptions_url\": \"https://api.github.com/users/arjankowski/subscriptions\",\n            \"organizations_url\": \"https://api.github.com/users/arjankowski/orgs\",\n            \"repos_url\": \"https://api.github.com/users/arjankowski/repos\",\n            \"events_url\": \"https://api.github.com/users/arjankowski/events{/privacy}\",\n            \"received_events_url\": \"https://api.github.com/users/arjankowski/received_events\",\n            \"type\": \"User\",\n            \"user_view_type\": \"public\",\n            \"site_admin\": false\n          },\n          \"content_type\": \"application/x-msdownload\",\n          \"state\": \"uploaded\",\n          \"size\": 42190440,\n          \"digest\": \"sha256:bf6e4d338526ee4fee47891e924ea156ed768dc3bad0e1e1e5cff6444fedaaaa\",\n          \"download_count\": 154,\n          \"created_at\": \"2025-10-21T16:05:00Z\",\n          \"updated_at\": \"2025-10-21T16:05:04Z\",\n          \"browser_download_url\": \"https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-x86.exe\"\n        }\n      ],\n      \"tarball_url\": \"https://api.github.com/repos/box/boxcli/tarball/v4.4.1\",\n      \"zipball_url\": \"https://api.github.com/repos/box/boxcli/zipball/v4.4.1\",\n      \"body\": \"### Bug Fixes\\r\\n\\r\\n* Fix the `--exempt-from-2fa` flag in `create` and `update` users commands ([#598](https://github.com/box/boxcli/issues/598)) ([8f897fe](https://github.com/box/boxcli/commit/8f897feb677a0089e7854aaf8ef6b2babb70ab16))\"\n    }\n  ]\n"
  },
  {
    "path": "test/fixtures/groups/get_group_memberships_id.json",
    "content": "{\n    \"type\": \"group_membership\",\n    \"id\": \"12345\",\n    \"user\": {\n        \"type\": \"user\",\n        \"id\": \"44444\",\n        \"name\": \"Test User 2\",\n        \"login\": \"testuser2@example.com\"\n    },\n    \"group\": {\n        \"type\": \"group\",\n        \"id\": \"11111\",\n        \"name\": \"Remote Employees\",\n        \"group_type\": \"managed_group\"\n    },\n    \"role\": \"admin\",\n    \"configurable_permissions\": {\n        \"can_create_accounts\": true,\n        \"can_edit_accounts\": true,\n        \"can_instant_login\": true,\n        \"can_run_reports\": true\n    },\n    \"created_at\": \"2018-04-25T15:39:35-07:00\",\n    \"modified_at\": \"2018-04-25T15:39:35-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/groups/get_groups_id.json",
    "content": "{\n    \"type\": \"group\",\n    \"id\": \"11111\",\n    \"name\": \"Employees\",\n    \"group_type\": \"managed_group\",\n    \"created_at\": \"2018-04-25T15:20:30-07:00\",\n    \"modified_at\": \"2018-04-25T15:20:30-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/groups/get_groups_id_collaborations_page_1.json",
    "content": "{\n\t\"total_count\": 2,\n\t\"entries\": [\n\t\t{\n\t\t\t\"type\": \"group_membership\",\n\t\t\t\"id\": \"1560354\",\n\t\t\t\"user\": {\n\t\t\t\t\"type\": \"user\",\n\t\t\t\t\"id\": \"13130406\",\n\t\t\t\t\"name\": \"Alison Wonderland\",\n\t\t\t\t\"login\": \"alice@gmail.com\"\n\t\t\t},\n\t\t\t\"group\": {\n\t\t\t\t\"type\": \"group\",\n\t\t\t\t\"id\": \"119720\",\n\t\t\t\t\"name\": \"family\"\n\t\t\t},\n\t\t\t\"role\": \"member\"\n        }\n    ],\n\t\"limit\": 1,\n\t\"offset\": 0\n}"
  },
  {
    "path": "test/fixtures/groups/get_groups_id_collaborations_page_2.json",
    "content": "{\n\t\"total_count\": 2,\n\t\"entries\": [\n\t\t{\n\t\t\t\"type\": \"group_membership\",\n\t\t\t\"id\": \"1560353\",\n\t\t\t\"user\": {\n\t\t\t\t\"type\": \"user\",\n\t\t\t\t\"id\": \"13130406\",\n\t\t\t\t\"name\": \"Alison Wonderland\",\n\t\t\t\t\"login\": \"alice2@gmail.com\"\n\t\t\t},\n\t\t\t\"group\": {\n\t\t\t\t\"type\": \"group\",\n\t\t\t\t\"id\": \"119720\",\n\t\t\t\t\"name\": \"family\"\n\t\t\t},\n\t\t\t\"role\": \"member\"\n        }\n    ],\n\t\"limit\": 1,\n\t\"offset\": 1\n}\n"
  },
  {
    "path": "test/fixtures/groups/get_groups_id_memberships_page_1.json",
    "content": "{\n    \"offset\": 0,\n    \"limit\": 1,\n    \"total_count\": 2,\n    \"entries\": [\n        {\n            \"type\": \"group_membership\",\n            \"id\": \"12345\",\n            \"user\": {\n                \"type\": \"user\",\n                \"id\": \"44444\",\n                \"name\": \"Test User 2\",\n                \"login\": \"testuser2@example.com\"\n            },\n            \"group\": {\n                \"type\": \"group\",\n                \"id\": \"11111\",\n                \"name\": \"Remote Employees\",\n                \"group_type\": \"managed_group\"\n            },\n            \"role\": \"member\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/groups/get_groups_id_memberships_page_2.json",
    "content": "{\n    \"offset\": 1,\n    \"limit\": 1,\n    \"total_count\": 2,\n    \"entries\": [\n        {\n            \"type\": \"group_membership\",\n            \"id\": \"123456\",\n            \"user\": {\n                \"type\": \"user\",\n                \"id\": \"444445\",\n                \"name\": \"Test User 2\",\n                \"login\": \"testuser2@example.com\"\n            },\n            \"group\": {\n                \"type\": \"group\",\n                \"id\": \"11111\",\n                \"name\": \"Remote Employees\",\n                \"group_type\": \"managed_group\"\n            },\n            \"role\": \"member\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/groups/get_groups_page_1.json",
    "content": "{\n    \"total_count\": 4,\n    \"entries\": [\n        {\n            \"type\": \"group\",\n            \"id\": \"22222\",\n            \"name\": \"Employees\",\n            \"group_type\": \"managed_group\"\n        },\n        {\n            \"type\": \"group\",\n            \"id\": \"11111\",\n            \"name\": \"Remote Employees\",\n            \"group_type\": \"managed_group\"\n        }\n    ],\n    \"limit\": 2,\n    \"offset\": 0\n}"
  },
  {
    "path": "test/fixtures/groups/get_groups_page_2.json",
    "content": "{\n    \"total_count\": 4,\n    \"entries\": [\n        {\n            \"type\": \"group\",\n            \"id\": \"222223\",\n            \"name\": \"Employees\",\n            \"group_type\": \"managed_group\"\n        },\n        {\n            \"type\": \"group\",\n            \"id\": \"11112\",\n            \"name\": \"Remote Employees\",\n            \"group_type\": \"managed_group\"\n        }\n    ],\n    \"limit\": 2,\n    \"offset\": 2\n}"
  },
  {
    "path": "test/fixtures/groups/post_group_memberships.json",
    "content": "{\n    \"type\": \"group_membership\",\n    \"id\": \"12345\",\n    \"user\": {\n        \"type\": \"user\",\n        \"id\": \"44444\",\n        \"name\": \"Test User 2\",\n        \"login\": \"testuser2@example.com\"\n    },\n    \"group\": {\n        \"type\": \"group\",\n        \"id\": \"11111\",\n        \"name\": \"Remote Employees\",\n        \"group_type\": \"managed_group\"\n    },\n    \"role\": \"admin\",\n    \"configurable_permissions\": {\n        \"can_create_accounts\": true,\n        \"can_edit_accounts\": true,\n        \"can_instant_login\": true,\n        \"can_run_reports\": true\n    },\n    \"created_at\": \"2018-04-25T15:39:35-07:00\",\n    \"modified_at\": \"2018-04-25T15:39:35-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/groups/post_groups.json",
    "content": "{\n    \"type\": \"group\",\n    \"id\": \"11111\",\n    \"name\": \"Employees\",\n    \"group_type\": \"managed_group\",\n    \"created_at\": \"2018-04-25T15:20:30-07:00\",\n    \"modified_at\": \"2018-04-25T15:20:30-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/groups/post_groups_terminate_sessions.json",
    "content": "{\n    \"message\": \"Request is successful, please check the admin events for the status of the job\"\n}\n"
  },
  {
    "path": "test/fixtures/groups/put_groups_id.json",
    "content": "{\n    \"type\": \"group\",\n    \"id\": \"11111\",\n    \"name\": \"Remote Employees\",\n    \"group_type\": \"managed_group\",\n    \"created_at\": \"2018-04-25T15:25:07-07:00\",\n    \"modified_at\": \"2018-04-25T15:31:02-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/hubs/get_hub_collaborations.json",
    "content": "{\n\t\"entries\": [\n\t\t{\n\t\t\t\"id\": \"99999\",\n\t\t\t\"type\": \"hub_collaboration\",\n\t\t\t\"hub\": {\n\t\t\t\t\"id\": \"12345\",\n\t\t\t\t\"type\": \"hubs\"\n\t\t\t},\n\t\t\t\"accessible_by\": {\n\t\t\t\t\"id\": \"22222\",\n\t\t\t\t\"type\": \"user\",\n\t\t\t\t\"name\": \"Editor Example\",\n\t\t\t\t\"login\": \"editor@example.com\"\n\t\t\t},\n\t\t\t\"role\": \"editor\",\n\t\t\t\"status\": \"accepted\"\n\t\t}\n\t],\n\t\"limit\": 1\n}\n"
  },
  {
    "path": "test/fixtures/hubs/get_hub_collaborations_id.json",
    "content": "{\n\t\"id\": \"99999\",\n\t\"type\": \"hub_collaboration\",\n\t\"hub\": {\n\t\t\"id\": \"12345\",\n\t\t\"type\": \"hubs\"\n\t},\n\t\"accessible_by\": {\n\t\t\"id\": \"22222\",\n\t\t\"type\": \"user\",\n\t\t\"name\": \"Editor Example\",\n\t\t\"login\": \"editor@example.com\"\n\t},\n\t\"role\": \"editor\",\n\t\"status\": \"accepted\"\n}\n"
  },
  {
    "path": "test/fixtures/hubs/get_hub_document_blocks.json",
    "content": "{\n\t\"entries\": [\n\t\t{\n\t\t\t\"id\": \"block_1\",\n\t\t\t\"type\": \"section_title\",\n\t\t\t\"parent_id\": \"page_1\",\n\t\t\t\"fragment\": \"Goals\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"block_2\",\n\t\t\t\"type\": \"item_list\",\n\t\t\t\"parent_id\": \"page_1\"\n\t\t}\n\t],\n\t\"type\": \"document_blocks\",\n\t\"limit\": 2\n}\n"
  },
  {
    "path": "test/fixtures/hubs/get_hub_document_pages.json",
    "content": "{\n\t\"entries\": [\n\t\t{\n\t\t\t\"id\": \"page_1\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"title_fragment\": \"Overview\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"page_2\",\n\t\t\t\"type\": \"page\",\n\t\t\t\"parent_id\": \"page_1\",\n\t\t\t\"title_fragment\": \"Launch Plan\"\n\t\t}\n\t],\n\t\"type\": \"document_pages\",\n\t\"limit\": 2\n}\n"
  },
  {
    "path": "test/fixtures/hubs/get_hub_items.json",
    "content": "{\n\t\"entries\": [\n\t\t{\n\t\t\t\"id\": \"11111\",\n\t\t\t\"type\": \"file\",\n\t\t\t\"name\": \"Q2 roadmap.pdf\"\n\t\t},\n\t\t{\n\t\t\t\"id\": \"22222\",\n\t\t\t\"type\": \"folder\",\n\t\t\t\"name\": \"Launch assets\"\n\t\t}\n\t],\n\t\"limit\": 2\n}\n"
  },
  {
    "path": "test/fixtures/hubs/get_hubs_id.json",
    "content": "{\n    \"id\": \"12345\",\n    \"type\": \"hubs\",\n    \"title\": \"Roadmap Hub\",\n    \"description\": \"Planning hub for the summer release\",\n    \"created_at\": \"2026-02-18T09:12:45.000Z\",\n    \"updated_at\": \"2026-04-10T14:28:11.000Z\",\n    \"created_by\": {\n        \"id\": \"11446498\",\n        \"type\": \"user\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"ceo@example.com\"\n    },\n    \"updated_by\": {\n        \"id\": \"11446498\",\n        \"type\": \"user\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"ceo@example.com\"\n    },\n    \"view_count\": 12,\n    \"is_ai_enabled\": true,\n    \"is_collaboration_restricted_to_enterprise\": false,\n    \"can_non_owners_invite\": true,\n    \"can_shared_link_be_created\": true,\n    \"can_public_shared_link_be_created\": false\n}\n"
  },
  {
    "path": "test/fixtures/hubs/post_hub_collaborations.json",
    "content": "{\n\t\"id\": \"99999\",\n\t\"type\": \"hub_collaboration\",\n\t\"hub\": {\n\t\t\"id\": \"12345\",\n\t\t\"type\": \"hubs\"\n\t},\n\t\"accessible_by\": {\n\t\t\"id\": \"22222\",\n\t\t\"type\": \"user\",\n\t\t\"name\": \"Editor Example\",\n\t\t\"login\": \"editor@example.com\"\n\t},\n\t\"role\": \"editor\",\n\t\"status\": \"accepted\"\n}\n"
  },
  {
    "path": "test/fixtures/hubs/post_hubs_id_manage_items.json",
    "content": "{\n\t\"operations\": [\n\t\t{\n\t\t\t\"action\": \"add\",\n\t\t\t\"item\": {\n\t\t\t\t\"id\": \"11111\",\n\t\t\t\t\"type\": \"file\"\n\t\t\t},\n\t\t\t\"parent_id\": \"67890\",\n\t\t\t\"status\": 201\n\t\t},\n\t\t{\n\t\t\t\"action\": \"remove\",\n\t\t\t\"item\": {\n\t\t\t\t\"id\": \"22222\",\n\t\t\t\t\"type\": \"folder\"\n\t\t\t},\n\t\t\t\"status\": 204\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "test/fixtures/hubs/put_hub_collaborations_id.json",
    "content": "{\n\t\"id\": \"99999\",\n\t\"type\": \"hub_collaboration\",\n\t\"hub\": {\n\t\t\"id\": \"12345\",\n\t\t\"type\": \"hubs\"\n\t},\n\t\"accessible_by\": {\n\t\t\"id\": \"22222\",\n\t\t\"type\": \"user\",\n\t\t\"name\": \"Editor Example\",\n\t\t\"login\": \"editor@example.com\"\n\t},\n\t\"role\": \"viewer\",\n\t\"status\": \"accepted\"\n}\n"
  },
  {
    "path": "test/fixtures/hubs/put_hubs_id.json",
    "content": "{\n    \"id\": \"12345\",\n    \"type\": \"hubs\",\n    \"title\": \"Updated Hub\",\n    \"description\": \"Updated description\",\n    \"created_at\": \"2026-02-18T09:12:45.000Z\",\n    \"updated_at\": \"2026-04-15T17:06:33.000Z\",\n    \"created_by\": {\n        \"id\": \"11446498\",\n        \"type\": \"user\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"ceo@example.com\"\n    },\n    \"updated_by\": {\n        \"id\": \"11446498\",\n        \"type\": \"user\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"ceo@example.com\"\n    },\n    \"view_count\": 27,\n    \"is_ai_enabled\": true,\n    \"is_collaboration_restricted_to_enterprise\": true,\n    \"can_non_owners_invite\": true,\n    \"can_shared_link_be_created\": false,\n    \"can_public_shared_link_be_created\": true\n}\n"
  },
  {
    "path": "test/fixtures/integration-mappings/get_integration_mappings_slack_page_1.json",
    "content": "{\n  \"entries\": [\n\t{\n\t  \"id\": \"123\",\n\t  \"integration_type\": \"slack\",\n\t  \"type\": \"integration_mapping\",\n\t  \"partner_item\": {\n\t\t\"type\": \"channel\",\n\t\t\"id\": \"ABC12378991223\",\n\t\t\"slack_workspace_id\": \"T12352314\",\n\t\t\"slack_org_id\": \"E1234567\"\n\t  },\n\t  \"box_item\": {\n\t\t\"id\": \"543\",\n\t\t\"etag\": \"1\",\n\t\t\"type\": \"folder\",\n\t\t\"name\": \"Contracts\",\n\t\t\"sequence_id\": \"3\"\n\t  },\n\t  \"is_manually_created\": true,\n\t  \"options\": {},\n\t  \"created_by\": {\n\t\t\"id\": \"11446498\",\n\t\t\"type\": \"user\",\n\t\t\"name\": \"Aaron Levie\",\n\t\t\"login\": \"ceo@example.com\"\n\t  },\n\t  \"modified_by\": {\n\t\t\"id\": \"11446498\",\n\t\t\"type\": \"user\",\n\t\t\"name\": \"Aaron Levie\",\n\t\t\"login\": \"ceo@example.com\"\n\t  },\n\t  \"created_at\": \"2012-12-12T10:53:43-08:00\",\n\t  \"modified_at\": \"2012-12-12T10:53:43-08:00\"\n\t}\n  ],\n  \"limit\": 1000,\n  \"next_marker\": \"ZDFARAFD\",\n  \"prev_marker\": null\n}\n"
  },
  {
    "path": "test/fixtures/integration-mappings/get_integration_mappings_slack_page_2.json",
    "content": "{\n  \"entries\": [\n\t{\n\t  \"id\": \"456\",\n\t  \"integration_type\": \"slack\",\n\t  \"type\": \"integration_mapping\",\n\t  \"partner_item\": {\n\t\t\"type\": \"channel\",\n\t\t\"id\": \"XYZ378991223\",\n\t\t\"slack_workspace_id\": \"T12352314\",\n\t\t\"slack_org_id\": \"E1234567\"\n\t  },\n\t  \"box_item\": {\n\t\t\"id\": \"987\",\n\t\t\"etag\": \"1\",\n\t\t\"type\": \"folder\",\n\t\t\"name\": \"Contracts\",\n\t\t\"sequence_id\": \"3\"\n\t  },\n\t  \"is_manually_created\": true,\n\t  \"options\": {},\n\t  \"created_by\": {\n\t\t\"id\": \"11446498\",\n\t\t\"type\": \"user\",\n\t\t\"name\": \"Aaron Levie\",\n\t\t\"login\": \"ceo@example.com\"\n\t  },\n\t  \"modified_by\": {\n\t\t\"id\": \"11446498\",\n\t\t\"type\": \"user\",\n\t\t\"name\": \"Aaron Levie\",\n\t\t\"login\": \"ceo@example.com\"\n\t  },\n\t  \"created_at\": \"2012-12-12T10:53:43-08:00\",\n\t  \"modified_at\": \"2012-12-12T10:53:43-08:00\"\n\t}\n  ],\n  \"limit\": 1000,\n  \"next_marker\": null,\n  \"prev_marker\": null\n}\n"
  },
  {
    "path": "test/fixtures/integration-mappings/get_integration_mappings_teams.json",
    "content": "{\n    \"entries\": [\n        {\n            \"id\": \"12345\",\n            \"type\": \"integration_mapping\",\n            \"box_item\": {\n                \"id\": \"42037322\",\n                \"type\": \"folder\"\n            },\n            \"created_at\": \"2012-12-12T10:53:43-08:00\",\n            \"integration_type\": \"teams\",\n            \"is_overridden_by_manual_mapping\": true,\n            \"modified_at\": \"2012-12-12T10:53:43-08:00\",\n            \"partner_item\": {\n                \"id\": \"19%3ABCD-Avgfggkggyftdtfgghjhkhkhh%40thread:tacv2\",\n                \"team_id\": \"hjgjgjg-bhhj-564a-b643-hghgj685u\",\n                \"tenant_id\": \"E1234567\",\n                \"type\": \"channel\"\n            }\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/integration-mappings/post_integration_mappings_slack.json",
    "content": "{\n    \"id\": \"12345\",\n    \"type\": \"integration_mapping\",\n    \"box_item\": {\n        \"id\": \"23456\",\n        \"type\": \"folder\",\n        \"etag\": \"1\",\n        \"name\": \"Contracts\",\n        \"sequence_id\": \"3\"\n    },\n    \"created_at\": \"2012-12-12T10:53:43-08:00\",\n    \"created_by\": {\n        \"id\": \"11446498\",\n        \"type\": \"user\",\n        \"login\": \"ceo@example.com\",\n        \"name\": \"Aaron Levie\"\n    },\n    \"integration_type\": \"slack\",\n    \"is_manually_created\": true,\n    \"modified_at\": \"2012-12-12T10:53:43-08:00\",\n    \"modified_by\": {\n        \"id\": \"11446498\",\n        \"type\": \"user\",\n        \"login\": \"ceo@example.com\",\n        \"name\": \"Aaron Levie\"\n    },\n    \"options\": {},\n    \"partner_item\": {\n        \"id\": \"C12378991223\",\n        \"type\": \"channel\",\n        \"slack_org_id\": \"E1234567\",\n        \"slack_workspace_id\": \"T12352314\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/integration-mappings/post_integration_mappings_teams.json",
    "content": "{\n    \"id\": \"12345\",\n    \"type\": \"integration_mapping\",\n    \"box_item\": {\n      \"id\": \"42037322\",\n      \"type\": \"folder\"\n    },\n    \"created_at\": \"2012-12-12T10:53:43-08:00\",\n    \"integration_type\": \"teams\",\n    \"is_overridden_by_manual_mapping\": true,\n    \"modified_at\": \"2012-12-12T10:53:43-08:00\",\n    \"partner_item\": {\n      \"id\": \"19%3ABCD-Avgfggkggyftdtfgghjhkhkhh%40thread:tacv2\",\n      \"type\": \"channel\",\n      \"team_id\": \"hjgjgjg-bhhj-564a-b643-hghgj685u\",\n      \"tenant_id\": \"E1234567\"\n    }\n  }"
  },
  {
    "path": "test/fixtures/integration-mappings/put_integration_mappings_slack_id.json",
    "content": "{\n    \"id\": \"12345\",\n    \"type\": \"integration_mapping\",\n    \"box_item\": {\n        \"id\": \"7890\",\n        \"type\": \"folder\",\n        \"etag\": \"1\",\n        \"name\": \"Contracts\",\n        \"sequence_id\": \"3\"\n    },\n    \"created_at\": \"2012-12-12T10:53:43-08:00\",\n    \"created_by\": {\n        \"id\": \"11446498\",\n        \"type\": \"user\",\n        \"login\": \"ceo@example.com\",\n        \"name\": \"Aaron Levie\"\n    },\n    \"integration_type\": \"slack\",\n    \"is_manually_created\": true,\n    \"modified_at\": \"2012-12-12T10:53:43-08:00\",\n    \"modified_by\": {\n        \"id\": \"11446498\",\n        \"type\": \"user\",\n        \"login\": \"ceo@example.com\",\n        \"name\": \"Aaron Levie\"\n    },\n    \"options\": {},\n    \"partner_item\": {\n        \"id\": \"C12378991223\",\n        \"type\": \"channel\",\n        \"slack_org_id\": \"E1234567\",\n        \"slack_workspace_id\": \"T12352314\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/integration-mappings/put_integration_mappings_teams_id.json",
    "content": "{\n    \"id\": \"12345\",\n    \"type\": \"integration_mapping\",\n    \"box_item\": {\n      \"id\": \"7890\",\n      \"type\": \"folder\"\n    },\n    \"created_at\": \"2012-12-12T10:53:43-08:00\",\n    \"integration_type\": \"teams\",\n    \"is_overridden_by_manual_mapping\": true,\n    \"modified_at\": \"2012-12-12T10:53:43-08:00\",\n    \"partner_item\": {\n      \"id\": \"19%3ABCD-Avgfggkggyftdtfgghjhkhkhh%40thread:tacv2\",\n      \"type\": \"channel\",\n      \"team_id\": \"hjgjgjg-bhhj-564a-b643-hghgj685u\",\n      \"tenant_id\": \"E1234567\"\n    }\n  }"
  },
  {
    "path": "test/fixtures/legal-hold-policies/get_file_version_legal_holds_id.json",
    "content": "{\n    \"type\": \"legal_hold\",\n    \"id\": \"99999\",\n    \"file_version\": {\n        \"type\": \"file_version\",\n        \"id\": \"77777\"\n    },\n    \"file\": {\n        \"type\": \"file\",\n        \"id\": \"88888\",\n        \"etag\": \"0\"\n    },\n    \"legal_hold_policy_assignments\": [\n        {\n            \"type\": \"legal_hold_policy_assignment\",\n            \"id\": \"12345\"\n        }\n    ],\n    \"deleted_at\": null\n}\n"
  },
  {
    "path": "test/fixtures/legal-hold-policies/get_file_version_legal_holds_page_1.json",
    "content": "{\n  \"next_marker\": \"ZDCE3\",  \n\t\"entries\": [\n        {\n            \"type\": \"legal_hold\",\n            \"id\": \"99999\"\n        }\n    ],\n    \"limit\": 100,\n    \"order\": [\n        {\n            \"by\": \"retention_policy_set_id, file_version_id\",\n            \"direction\": \"ASC\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/legal-hold-policies/get_file_version_legal_holds_page_2.json",
    "content": "{ \n\t\"entries\": [\n        {\n            \"type\": \"legal_hold\",\n            \"id\": \"99990\"\n        }\n    ],\n    \"limit\": 100,\n    \"order\": [\n        {\n            \"by\": \"retention_policy_set_id, file_version_id\",\n            \"direction\": \"ASC\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/legal-hold-policies/get_legal_hold_policies.json",
    "content": "{\n    \"entries\": [\n        {\n            \"type\": \"legal_hold_policy\",\n            \"id\": \"22222\",\n            \"policy_name\": \"IRS Audit\"\n        },\n        {\n            \"type\": \"legal_hold_policy\",\n            \"id\": \"11111\",\n            \"policy_name\": \"Trial Documents\"\n        }\n    ],\n    \"limit\": 100,\n    \"order\": [\n        {\n            \"by\": \"policy_name\",\n            \"direction\": \"ASC\"\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/legal-hold-policies/get_legal_hold_policies_id.json",
    "content": "{\n    \"type\": \"legal_hold_policy\",\n    \"id\": \"11111\",\n    \"policy_name\": \"Trial Documents\",\n    \"description\": \"\",\n    \"status\": \"active\",\n    \"assignment_counts\": {\n        \"user\": 0,\n        \"folder\": 0,\n        \"file\": 0,\n        \"file_version\": 0\n    },\n    \"is_ongoing\": true,\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"created_at\": \"2018-04-25T16:37:05-07:00\",\n    \"modified_at\": \"2018-04-25T16:37:05-07:00\",\n    \"deleted_at\": null,\n    \"filter_started_at\": null,\n    \"filter_ended_at\": null\n}\n"
  },
  {
    "path": "test/fixtures/legal-hold-policies/get_legal_hold_policy_assignments_id.json",
    "content": "{\n    \"type\": \"legal_hold_policy_assignment\",\n    \"id\": \"12345\",\n    \"legal_hold_policy\": {\n        \"type\": \"legal_hold_policy\",\n        \"id\": \"11111\",\n        \"policy_name\": \"Trial Documents\"\n    },\n    \"assigned_to\": {\n        \"type\": \"folder\",\n        \"id\": \"55555\"\n    },\n    \"assigned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"assigned_at\": \"2018-04-25T17:07:56-07:00\",\n    \"deleted_at\": null,\n    \"modified_at\": \"2018-04-25T17:07:57-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/legal-hold-policies/get_legal_hold_policy_assignments_policy_id_page_1.json",
    "content": "{\n  \"next_marker\": \"ZDCE3\",  \n\t\"entries\": [\n        {\n            \"type\": \"legal_hold_policy_assignment\",\n            \"id\": \"12345\"\n        }\n    ],\n    \"limit\": 1,\n    \"order\": [\n        {\n            \"by\": \"retention_policy_id, retention_policy_object_id\",\n            \"direction\": \"ASC\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/legal-hold-policies/get_legal_hold_policy_assignments_policy_id_page_2.json",
    "content": "{ \n\t\"entries\": [\n        {\n            \"type\": \"legal_hold_policy_assignment\",\n            \"id\": \"123456\"\n        }\n    ],\n    \"limit\": 1,\n    \"order\": [\n        {\n            \"by\": \"retention_policy_id, retention_policy_object_id\",\n            \"direction\": \"ASC\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/legal-hold-policies/post_legal_hold_policies.json",
    "content": "{\n    \"type\": \"legal_hold_policy\",\n    \"id\": \"11111\",\n    \"policy_name\": \"Trial Documents\",\n    \"description\": \"\",\n    \"status\": \"active\",\n    \"assignment_counts\": {\n        \"user\": 0,\n        \"folder\": 0,\n        \"file\": 0,\n        \"file_version\": 0\n    },\n    \"is_ongoing\": true,\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"created_at\": \"2018-04-25T16:37:05-07:00\",\n    \"modified_at\": \"2018-04-25T16:37:05-07:00\",\n    \"deleted_at\": null,\n    \"filter_started_at\": null,\n    \"filter_ended_at\": null\n}\n"
  },
  {
    "path": "test/fixtures/legal-hold-policies/post_legal_hold_policy_assignments.json",
    "content": "{\n    \"type\": \"legal_hold_policy_assignment\",\n    \"id\": \"12345\",\n    \"legal_hold_policy\": {\n        \"type\": \"legal_hold_policy\",\n        \"id\": \"11111\",\n        \"policy_name\": \"Trial Documents\"\n    },\n    \"assigned_to\": {\n        \"type\": \"folder\",\n        \"id\": \"55555\"\n    },\n    \"assigned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"assigned_at\": \"2018-04-25T17:07:56-07:00\",\n    \"deleted_at\": null,\n    \"modified_at\": \"2018-04-25T17:07:57-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/legal-hold-policies/put_legal_hold_policies_id.json",
    "content": "{\n    \"type\": \"legal_hold_policy\",\n    \"id\": \"11111\",\n    \"policy_name\": \"Trial Documents\",\n    \"description\": \"Documents related to our ongoing litigation\",\n    \"status\": \"active\",\n    \"assignment_counts\": {\n        \"user\": 0,\n        \"folder\": 0,\n        \"file\": 0,\n        \"file_version\": 0\n    },\n    \"is_ongoing\": true,\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"created_at\": \"2018-04-25T16:37:05-07:00\",\n    \"modified_at\": \"2018-04-25T16:45:55-07:00\",\n    \"deleted_at\": null,\n    \"filter_started_at\": null,\n    \"filter_ended_at\": null\n}\n"
  },
  {
    "path": "test/fixtures/metadata-cascade-policies/get_metadata_cascade_policies_folder_id_200.json",
    "content": "{\n    \"limit\": 100,\n    \"entries\": [\n        {\n            \"id\": \"84113349-794d-445c-b93c-d8481b223434\",\n            \"type\": \"metadata_cascade_policy\",\n            \"owner_enterprise\": {\n                \"type\": \"enterprise\",\n                \"id\": \"11111\"\n            },\n            \"parent\": {\n                \"type\": \"folder\",\n                \"id\": \"22222\"\n            },\n            \"scope\": \"enterprise_11111\",\n            \"templateKey\": \"testTemplate\"\n        }\n    ],\n    \"next_marker\": null,\n    \"prev_marker\": null\n}"
  },
  {
    "path": "test/fixtures/metadata-cascade-policies/get_metadata_cascade_policies_id_200.json",
    "content": "{\n    \"id\": \"84113349-794d-445c-b93c-d8481b223434\",\n    \"type\": \"metadata_cascade_policy\",\n    \"owner_enterprise\": {\n        \"type\": \"enterprise\",\n        \"id\": \"11111\"\n    },\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"22222\"\n    },\n    \"scope\": \"enterprise_11111\",\n    \"templateKey\": \"testTemplate\"\n}\n"
  },
  {
    "path": "test/fixtures/metadata-cascade-policies/post_metadata_cascade_policies_201.json",
    "content": "{\n    \"id\": \"84113349-794d-445c-b93c-d8481b223434\",\n    \"type\": \"metadata_cascade_policy\",\n    \"owner_enterprise\": {\n        \"type\": \"enterprise\",\n        \"id\": \"11111\"\n    },\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"22222\"\n    },\n    \"scope\": \"enterprise_11111\",\n    \"templateKey\": \"testTemplate\"\n}\n"
  },
  {
    "path": "test/fixtures/metadata-query/post_metadata_queries_execute_read.json",
    "content": "{\n    \"id\": 12345,\n    \"etag\": 1,\n    \"type\": \"file\",\n    \"sequence_id\": 3,\n    \"name\": \"Contract.pdf\",\n    \"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\",\n    \"file_version\": {\n        \"id\": 12345,\n        \"type\": \"file_version\",\n        \"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n    },\n    \"description\": \"Contract for Q1 renewal\",\n    \"size\": 629644,\n    \"path_collection\": {\n        \"total_count\": 1,\n        \"entries\": [\n            {\n                \"id\": 12345,\n                \"etag\": 1,\n                \"type\": \"folder\",\n                \"sequence_id\": 3,\n                \"name\": \"Contracts\"\n            }\n        ]\n    },\n    \"created_at\": \"2012-12-12T10:53:43-08:00\",\n    \"modified_at\": \"2012-12-12T10:53:43-08:00\",\n    \"trashed_at\": \"2012-12-12T10:53:43-08:00\",\n    \"purged_at\": \"2012-12-12T10:53:43-08:00\",\n    \"content_created_at\": \"2012-12-12T10:53:43-08:00\",\n    \"content_modified_at\": \"2012-12-12T10:53:43-08:00\",\n    \"created_by\": {\n        \"id\": 11446498,\n        \"type\": \"user\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"ceo@example.com\"\n    },\n    \"modified_by\": {\n        \"id\": 11446498,\n        \"type\": \"user\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"ceo@example.com\"\n    },\n    \"owned_by\": {\n        \"id\": 11446498,\n        \"type\": \"user\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"ceo@example.com\"\n    },\n    \"shared_link\": {\n        \"url\": \"https://www.box.com/s/vspke7y05sb214wjokpk\",\n        \"download_url\": \"https://www.box.com/shared/static/rh935iit6ewrmw0unyul.jpeg\",\n        \"vanity_url\": \"https://acme.app.box.com/v/my_url/\",\n        \"vanity_name\": \"my_url\",\n        \"access\": \"open\",\n        \"effective_access\": \"company\",\n        \"effective_permission\": \"can_download\",\n        \"unshared_at\": \"2018-04-13T13:53:23-07:00\",\n        \"is_password_enabled\": true,\n        \"permissions\": {\n            \"can_download\": true,\n            \"can_preview\": true\n        },\n        \"download_count\": 3,\n        \"preview_count\": 3\n    },\n    \"parent\": {\n        \"id\": 12345,\n        \"etag\": 1,\n        \"type\": \"folder\",\n        \"sequence_id\": 3,\n        \"name\": \"Contracts\"\n    },\n    \"item_status\": \"active\"\n}\n"
  },
  {
    "path": "test/fixtures/metadata-templates/get_metadata_templates_scope_page_1.json",
    "content": "{\n    \"limit\": 2,\n    \"entries\": [\n        {\n            \"id\": \"71274d65-cf63-40dc-b119-d4da31071492\",\n            \"type\": \"metadata_template\",\n            \"templateKey\": \"mymetadata\",\n            \"scope\": \"enterprise_12345\",\n            \"displayName\": \"MyMetadata\",\n            \"hidden\": false,\n            \"fields\": [\n                {\n                    \"id\": \"6ff16602-0119-4619-ae15-f02b1ecdd811\",\n                    \"type\": \"string\",\n                    \"key\": \"data\",\n                    \"displayName\": \"Data\",\n                    \"hidden\": false\n                },\n                {\n                    \"id\": \"5c16d86c-6554-4278-814e-356211215807\",\n                    \"type\": \"date\",\n                    \"key\": \"when\",\n                    \"displayName\": \"When\",\n                    \"hidden\": false\n                }\n            ]\n        },\n        {\n            \"id\": \"1ba164d2-c223-4797-92a9-1616b29c3f72\",\n            \"type\": \"metadata_template\",\n            \"templateKey\": \"testTemplate\",\n            \"scope\": \"enterprise_12345\",\n            \"displayName\": \"Test Template\",\n            \"hidden\": false,\n            \"fields\": [\n                {\n                    \"id\": \"1f1f29a6-00e2-4b56-b446-b50d5491b0ca\",\n                    \"type\": \"enum\",\n                    \"key\": \"testEnum\",\n                    \"displayName\": \"Test Enum\",\n                    \"hidden\": false,\n                    \"options\": [\n                        {\n                            \"id\": \"c84b16d2-db68-4fc2-9a85-4b8820841fa8\",\n                            \"key\": \"foo\"\n                        },\n                        {\n                            \"id\": \"6ee108f2-47f0-43e2-9584-06311c37badf\",\n                            \"key\": \"bar\"\n                        }\n                    ]\n                }\n            ]\n        }\n    ],\n    \"next_marker\": \"ZDFARAFD\",\n    \"prev_marker\": null\n}"
  },
  {
    "path": "test/fixtures/metadata-templates/get_metadata_templates_scope_page_2.json",
    "content": "{\n    \"limit\": 2,\n    \"entries\": [\n        {\n            \"id\": \"81274d65-cf63-40dc-b119-d4da31071492\",\n            \"type\": \"metadata_template\",\n            \"templateKey\": \"mymetadata\",\n            \"scope\": \"enterprise_12345\",\n            \"displayName\": \"MyMetadata\",\n            \"hidden\": false,\n            \"fields\": [\n                {\n                    \"id\": \"6ff16602-0119-4619-ae15-f02b1ecdd811\",\n                    \"type\": \"string\",\n                    \"key\": \"data\",\n                    \"displayName\": \"Data\",\n                    \"hidden\": false\n                },\n                {\n                    \"id\": \"5c16d86c-6554-4278-814e-356211215807\",\n                    \"type\": \"date\",\n                    \"key\": \"when\",\n                    \"displayName\": \"When\",\n                    \"hidden\": false\n                }\n            ]\n        },\n        {\n            \"id\": \"8ba164d2-c223-4797-92a9-1616b29c3f72\",\n            \"type\": \"metadata_template\",\n            \"templateKey\": \"testTemplate\",\n            \"scope\": \"enterprise_12345\",\n            \"displayName\": \"Test Template\",\n            \"hidden\": false,\n            \"fields\": [\n                {\n                    \"id\": \"1f1f29a6-00e2-4b56-b446-b50d5491b0ca\",\n                    \"type\": \"enum\",\n                    \"key\": \"testEnum\",\n                    \"displayName\": \"Test Enum\",\n                    \"hidden\": false,\n                    \"options\": [\n                        {\n                            \"id\": \"c84b16d2-db68-4fc2-9a85-4b8820841fa8\",\n                            \"key\": \"foo\"\n                        },\n                        {\n                            \"id\": \"6ee108f2-47f0-43e2-9584-06311c37badf\",\n                            \"key\": \"bar\"\n                        }\n                    ]\n                }\n            ]\n        }\n    ],\n    \"next_marker\": null,\n    \"prev_marker\": null\n}"
  },
  {
    "path": "test/fixtures/metadata-templates/get_metadata_templates_scope_template_schema.json",
    "content": "{\n    \"id\": \"1ba96432-c223-4797-95a9-1636b59c3f7b\",\n    \"type\": \"metadata_template\",\n    \"templateKey\": \"testTemplate\",\n    \"scope\": \"enterprise_12345\",\n    \"displayName\": \"Test Template\",\n    \"hidden\": false,\n    \"fields\": [\n        {\n            \"id\": \"1f2f29a6-00e2-4b56-b246-b50d5494b2ca\",\n            \"type\": \"enum\",\n            \"key\": \"testEnum\",\n            \"displayName\": \"Test Enum\",\n            \"hidden\": false,\n            \"options\": [\n                {\n                    \"id\": \"c84b76d2-db68-4fc2-9a75-4b7820845fa8\",\n                    \"key\": \"foo\"\n                },\n                {\n                    \"id\": \"6ee108f2-41f0-43e2-1584-06316c37badf\",\n                    \"key\": \"bar\"\n                }\n            ]\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/metadata-templates/post_metadata_templates_schema.json",
    "content": "{\n    \"id\": \"687735ca-1325-4e50-8f30-6d4683997fa4\",\n    \"type\": \"metadata_template\",\n    \"templateKey\": \"newMetadata\",\n    \"scope\": \"enterprise_12345\",\n    \"displayName\": \"New Metadata Template\",\n    \"hidden\": true,\n    \"copyInstanceOnItemCopy\": true,\n    \"fields\": [\n        {\n            \"id\": \"3c7ba014-e136-49e3-a0aa-f48588ddd223\",\n            \"type\": \"string\",\n            \"key\": \"name\",\n            \"displayName\": \"Name\",\n            \"hidden\": false\n        },\n        {\n            \"id\": \"eb30bfc1-a165-4439-bec3-53e349ee7671\",\n            \"type\": \"enum\",\n            \"key\": \"location\",\n            \"displayName\": \"Location\",\n            \"hidden\": false,\n            \"options\": [\n                {\n                    \"id\": \"b8435f07-e332-4493-9add-18aeaed73551\",\n                    \"key\": \"US\"\n                },\n                {\n                    \"id\": \"4cdb3b26-5bba-4433-b8b8-22b89f372735\",\n                    \"key\": \"EU\"\n                }\n            ]\n        },\n        {\n            \"id\": \"6e311d0e-7133-4b72-a3aa-199c723796e3\",\n            \"type\": \"date\",\n            \"key\": \"date\",\n            \"displayName\": \"Date\",\n            \"hidden\": false\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/metadata-templates/put_metadata_templates_scope_key_schema_200.json",
    "content": "{\n    \"templateKey\": \"employeeRecord\",\n    \"scope\": \"enterprise_11111\",\n    \"displayName\": \"New Display Name\",\n    \"hidden\": true,\n    \"copyInstanceOnItemCopy\": true,\n    \"fields\": [\n        {\n            \"type\": \"string\",\n            \"key\": \"key3\",\n            \"displayName\": \"Third Field\",\n            \"hidden\": true\n        },\n        {\n            \"type\": \"enum\",\n            \"key\": \"key1\",\n            \"displayName\": \"First Key\",\n            \"options\": [\n                {\n                    \"key\": \"optionKey0\"\n                },\n                {\n                    \"key\": \"optionKey1\"\n                },\n                {\n                    \"key\": \"optionKey2\"\n                }\n            ]\n        },\n        {\n            \"type\": \"multiSelect\",\n            \"displayName\": \"foo\",\n            \"hidden\": false,\n            \"options\": [\n                {\n                    \"key\": \"bar\"\n                },\n                {\n                    \"key\": \"baz\"\n                }\n            ]\n        },\n        {\n            \"type\": \"float\",\n            \"displayName\": \"Count\"\n        },\n        {\n            \"type\": \"date\",\n            \"displayName\": \"Date\"\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/output/bulk_collection_output_csv.txt",
    "content": "type,id,item.type,item.id,item.file_version.type,item.file_version.id,item.file_version.sha1,item.sequence_id,item.etag,item.sha1,item.name\ntask,11111,file,1234567890,file_version,22222,6afc05eae22e994f1c7dd48e58f8895dd9028223,0,0,6afc05eae22e994f1c7dd48e58f8895dd9028223,Tasks file.txt\ntask,111112,file,1234567890,file_version,22222,6afc05eae22e994f1c7dd48e58f8895dd9028223,0,0,6afc05eae22e994f1c7dd48e58f8895dd9028223,Tasks file.txt\ntask,11111,file,1234567890,file_version,22222,6afc05eae22e994f1c7dd48e58f8895dd9028223,0,0,6afc05eae22e994f1c7dd48e58f8895dd9028223,Tasks file.txt\ntask,111112,file,1234567890,file_version,22222,6afc05eae22e994f1c7dd48e58f8895dd9028223,0,0,6afc05eae22e994f1c7dd48e58f8895dd9028223,Tasks file.txt\ntask,11111,file,1234567890,file_version,22222,6afc05eae22e994f1c7dd48e58f8895dd9028223,0,0,6afc05eae22e994f1c7dd48e58f8895dd9028223,Tasks file.txt\ntask,111112,file,1234567890,file_version,22222,6afc05eae22e994f1c7dd48e58f8895dd9028223,0,0,6afc05eae22e994f1c7dd48e58f8895dd9028223,Tasks file.txt\n"
  },
  {
    "path": "test/fixtures/output/bulk_collection_output_json.txt",
    "content": "[\n    {\n        \"type\": \"task\",\n        \"id\": \"11111\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"1234567890\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"22222\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"Tasks file.txt\"\n        },\n        \"due_at\": null\n    },\n    {\n        \"type\": \"task\",\n        \"id\": \"111112\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"1234567890\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"22222\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"Tasks file.txt\"\n        },\n        \"due_at\": null\n    },\n    {\n        \"type\": \"task\",\n        \"id\": \"11111\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"1234567890\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"22222\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"Tasks file.txt\"\n        },\n        \"due_at\": null\n    },\n    {\n        \"type\": \"task\",\n        \"id\": \"111112\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"1234567890\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"22222\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"Tasks file.txt\"\n        },\n        \"due_at\": null\n    },\n    {\n        \"type\": \"task\",\n        \"id\": \"11111\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"1234567890\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"22222\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"Tasks file.txt\"\n        },\n        \"due_at\": null\n    },\n    {\n        \"type\": \"task\",\n        \"id\": \"111112\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"1234567890\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"22222\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"Tasks file.txt\"\n        },\n        \"due_at\": null\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/bulk_collection_output_table.txt",
    "content": "----- Task 11111 -----\nType: task\nID: '11111'\nItem:\n    Type: file\n    ID: '1234567890'\n    File Version:\n        Type: file_version\n        ID: '22222'\n        SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Sequence ID: '0'\n    ETag: '0'\n    SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Name: Tasks file.txt\nDue At: null\n\n----- Task 111112 -----\nType: task\nID: '111112'\nItem:\n    Type: file\n    ID: '1234567890'\n    File Version:\n        Type: file_version\n        ID: '22222'\n        SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Sequence ID: '0'\n    ETag: '0'\n    SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Name: Tasks file.txt\nDue At: null\n\n----- Task 11111 -----\nType: task\nID: '11111'\nItem:\n    Type: file\n    ID: '1234567890'\n    File Version:\n        Type: file_version\n        ID: '22222'\n        SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Sequence ID: '0'\n    ETag: '0'\n    SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Name: Tasks file.txt\nDue At: null\n\n----- Task 111112 -----\nType: task\nID: '111112'\nItem:\n    Type: file\n    ID: '1234567890'\n    File Version:\n        Type: file_version\n        ID: '22222'\n        SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Sequence ID: '0'\n    ETag: '0'\n    SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Name: Tasks file.txt\nDue At: null\n\n----- Task 11111 -----\nType: task\nID: '11111'\nItem:\n    Type: file\n    ID: '1234567890'\n    File Version:\n        Type: file_version\n        ID: '22222'\n        SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Sequence ID: '0'\n    ETag: '0'\n    SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Name: Tasks file.txt\nDue At: null\n\n----- Task 111112 -----\nType: task\nID: '111112'\nItem:\n    Type: file\n    ID: '1234567890'\n    File Version:\n        Type: file_version\n        ID: '22222'\n        SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Sequence ID: '0'\n    ETag: '0'\n    SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Name: Tasks file.txt\nDue At: null\n"
  },
  {
    "path": "test/fixtures/output/bulk_items_output_csv.txt",
    "content": "type,id,sequence_id,etag,name,file_version.type,file_version.id,file_version.sha1,sha1,url\nfolder,1234567,10,10,Box,,,,,\nfolder,22585432,9,9,Human Resources,,,,,\nfolder,24432981,8,8,Engineering,,,,,\nfile,124000,79,79,Draymond.boxnote,file_version,431000,b7e432rew9bc2850a5780a86a25a8574d1b473f,b7e9fsdfe329bc2850a5780a86a25a8574d1b473f,\nweb_link,13413421543,77,77,77 Crunchy Dragon Rolls,,,,,https://cloud.app.box.com/s/432fesr32fsdfw\n"
  },
  {
    "path": "test/fixtures/output/bulk_output_json.txt",
    "content": "[\n    {\n        \"type\": \"collaboration\",\n        \"id\": \"1234567890\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"9753108642\",\n            \"name\": \"Inviting User\",\n            \"login\": \"invites@example.com\"\n        },\n        \"created_at\": \"2016-11-16T21:33:31-08:00\",\n        \"modified_at\": \"2016-11-16T21:33:31-08:00\",\n        \"expires_at\": null,\n        \"status\": \"accepted\",\n        \"accessible_by\": {\n            \"type\": \"user\",\n            \"id\": \"987654321\",\n            \"name\": \"Steve Jobs\",\n            \"login\": \"steve.jobs@example.com\"\n        },\n        \"role\": \"previewer\",\n        \"acknowledged_at\": \"2016-11-16T21:33:31-08:00\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"11111\",\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"name\": \"Collaborated File\"\n        }\n    },\n    {\n        \"type\": \"collaboration\",\n        \"id\": \"1234567891\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"9753108642\",\n            \"name\": \"Inviting User\",\n            \"login\": \"invites@example.com\"\n        },\n        \"created_at\": \"2016-11-16T21:33:31-08:00\",\n        \"modified_at\": \"2016-11-16T21:33:31-08:00\",\n        \"expires_at\": null,\n        \"status\": \"accepted\",\n        \"accessible_by\": {\n            \"type\": \"user\",\n            \"id\": \"987654322\",\n            \"name\": \"Roger Federer\",\n            \"login\": \"roger.federer@example.com\"\n        },\n        \"role\": \"previewer\",\n        \"acknowledged_at\": \"2016-11-16T21:33:31-08:00\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"22222\",\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"name\": \"Collaborated File\"\n        }\n    },\n    {\n        \"type\": \"collaboration\",\n        \"id\": \"1234567892\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"9753108642\",\n            \"name\": \"Inviting User\",\n            \"login\": \"invites@example.com\"\n        },\n        \"created_at\": \"2016-11-16T21:33:31-08:00\",\n        \"modified_at\": \"2016-11-16T21:33:31-08:00\",\n        \"expires_at\": null,\n        \"status\": \"accepted\",\n        \"accessible_by\": {\n            \"type\": \"user\",\n            \"id\": \"987654323\",\n            \"name\": \"Dominic Toretto\",\n            \"login\": \"dominic.toretto@example.com\"\n        },\n        \"role\": \"previewer\",\n        \"acknowledged_at\": \"2016-11-16T21:33:31-08:00\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"33333\",\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"name\": \"Collaborated File\"\n        }\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/collaboration_whitelist_add_yaml.txt",
    "content": "Type: collaboration_whitelist_entry\nID: '1234'\nDomain: test.com\nDirection: both\nEnterprise:\n    Type: enterprise\n    ID: '12345678'\n    Name: Box\nCreated At: '2017-12-06T15:05:28-08:00'\nModified At: '2017-12-06T15:05:28-08:00'\n"
  },
  {
    "path": "test/fixtures/output/collaboration_whitelist_create_exemption_yaml.txt",
    "content": "Type: collaboration_whitelist_exempt_target\nID: '1234'\nUser:\n    Type: user\n    ID: '5678'\n    Name: example user\n    Login: test@example.com\nEnterprise:\n    Type: enterprise\n    ID: '12345678'\n    Name: Box\nCreated At: '2017-12-06T16:57:17-08:00'\nModified At: '2017-12-06T16:57:17-08:00'\n"
  },
  {
    "path": "test/fixtures/output/collaboration_whitelist_get_exemption_yaml.txt",
    "content": "Type: collaboration_whitelist_exempt_target\nID: '11111'\nUser:\n    Type: user\n    ID: '22222'\n    Name: Test User\n    Login: testuser@example.com\nEnterprise:\n    Type: enterprise\n    ID: '33333'\n    Name: Test Enterprise\nCreated At: '2018-04-23T21:45:12-07:00'\nModified At: '2018-04-23T21:45:12-07:00'\n"
  },
  {
    "path": "test/fixtures/output/collaboration_whitelist_get_yaml.txt",
    "content": "Type: collaboration_whitelist_entry\nID: '11111'\nDomain: box.com\nDirection: both\nEnterprise:\n    Type: enterprise\n    ID: '22222'\n    Name: Test Enterprise\nCreated At: '2018-04-23T21:31:07-07:00'\nModified At: '2018-04-23T21:31:07-07:00'\n"
  },
  {
    "path": "test/fixtures/output/collaboration_whitelist_list_exemptions_json.txt",
    "content": "[\n    {\n        \"type\": \"collaboration_whitelist_exempt_target\",\n        \"id\": \"11111\",\n        \"user\": {\n            \"type\": \"user\",\n            \"id\": \"22222\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        }\n    },\n    {\n        \"type\": \"collaboration_whitelist_exempt_target\",\n        \"id\": \"111112\",\n        \"user\": {\n            \"type\": \"user\",\n            \"id\": \"22222\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        }\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/collaboration_whitelist_list_json.txt",
    "content": "[\n    {\n        \"type\": \"collaboration_whitelist_entry\",\n        \"id\": \"11111\",\n        \"domain\": \"box.com\",\n        \"direction\": \"both\"\n    },\n    {\n        \"type\": \"collaboration_whitelist_entry\",\n        \"id\": \"111112\",\n        \"domain\": \"box.com\",\n        \"direction\": \"both\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/collaborations_add_login_yaml.txt",
    "content": "Type: collaboration\nID: '1234567890'\nCreated By:\n    Type: user\n    ID: '9753108642'\n    Name: Inviting User\n    Login: invites@example.com\nCreated At: '2016-11-16T21:33:31-08:00'\nModified At: '2016-11-16T21:33:31-08:00'\nExpires At: null\nStatus: accepted\nAccessible By:\n    Type: user\n    ID: '987654321'\n    Name: My New Friend\n    Login: newfriend@example.com\nRole: previewer\nAcknowledged At: '2016-11-16T21:33:31-08:00'\nItem:\n    Type: file\n    ID: '1234567890'\n    Sequence ID: '0'\n    ETag: '0'\n    Name: Collaborated File\n"
  },
  {
    "path": "test/fixtures/output/collaborations_get_pending_json.txt",
    "content": "[\n    {\n        \"type\": \"collaboration\",\n        \"id\": \"1234567890\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"9087654321\",\n            \"name\": \"Some Other User\",\n            \"login\": \"otheruser@example.com\"\n        },\n        \"created_at\": \"2016-11-16T20:52:34-08:00\",\n        \"modified_at\": \"2016-11-16T20:52:34-08:00\",\n        \"expires_at\": null,\n        \"status\": \"pending\",\n        \"accessible_by\": {\n            \"type\": \"user\",\n            \"id\": \"132467469\",\n            \"name\": \"Current User\",\n            \"login\": \"me@example.com\"\n        },\n        \"role\": \"editor\",\n        \"acknowledged_at\": null,\n        \"item\": null\n    },\n    {\n        \"type\": \"collaboration\",\n        \"id\": \"1234567890\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"9087654320\",\n            \"name\": \"Some Other User\",\n            \"login\": \"otheruser@example.com\"\n        },\n        \"created_at\": \"2016-11-16T20:52:34-08:00\",\n        \"modified_at\": \"2016-11-16T20:52:34-08:00\",\n        \"expires_at\": null,\n        \"status\": \"pending\",\n        \"accessible_by\": {\n            \"type\": \"user\",\n            \"id\": \"132467469\",\n            \"name\": \"Current User\",\n            \"login\": \"me@example.com\"\n        },\n        \"role\": \"editor\",\n        \"acknowledged_at\": null,\n        \"item\": null\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/collaborations_get_yaml.txt",
    "content": "Type: collaboration\nID: '1234567890'\nCreated By:\n    Type: user\n    ID: '123456789'\n    Name: Aaron Levie\n    Login: aaron@example.com\nCreated At: '2015-07-09T16:37:27-07:00'\nModified At: '2016-08-30T14:35:32-07:00'\nExpires At: null\nStatus: accepted\nAccessible By:\n    Type: user\n    ID: '1357924680'\n    Name: Dylan Smith\n    Login: dylan@example.com\nRole: editor\nAcknowledged At: '2015-07-09T16:37:27-07:00'\nItem:\n    Type: folder\n    ID: '3936621105'\n    Sequence ID: '2'\n    ETag: '2'\n    Name: 150630. Recents\n"
  },
  {
    "path": "test/fixtures/output/collaborations_update_yaml.txt",
    "content": "Type: collaboration\nID: '1234567890'\nCreated By:\n    Type: user\n    ID: '834098476'\n    Name: Inviting User\n    Login: inviter@example.com\nCreated At: '2015-11-03T18:36:37-08:00'\nModified At: '2016-11-16T21:01:19-08:00'\nExpires At: null\nStatus: accepted\nAccessible By:\n    Type: user\n    ID: '6789234576'\n    Name: Collaborated User\n    Login: collaborator@example.com\nRole: viewer\nAcknowledged At: '2015-11-03T18:36:37-08:00'\nItem:\n    Type: folder\n    ID: '9087654321'\n    Sequence ID: '1'\n    ETag: '1'\n    Name: Collaborated Folder\n"
  },
  {
    "path": "test/fixtures/output/collections_get_json.txt",
    "content": "[\n    {\n        \"type\": \"collection\",\n        \"id\": \"123456789\",\n        \"name\": \"Favorites\",\n        \"collection_type\": \"favorites\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/collections_get_table.txt",
    "content": "----- Collection 123456789 -----\nType: collection\nID: '123456789'\nName: Favorites\nCollection Type: favorites\n"
  },
  {
    "path": "test/fixtures/output/collections_list_items_json.txt",
    "content": "[\n    {\n        \"type\": \"folder\",\n        \"id\": \"192429928\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"name\": \"Stephen Curry Three Pointers\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"818853862\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"Warriors.jpg\"\n    },\n    {\n        \"type\": \"folder\",\n        \"id\": \"192429928\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"name\": \"Roger Federer Grandslams\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"818853862\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"Basel.jpg\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/comments_create_yaml.txt",
    "content": "Type: comment\nID: '9988776655'\nIs Reply Comment: false\nMessage: Other User Looks good!\nCreated By:\n    Type: user\n    ID: '123456789'\n    Name: Matt Willer\n    Login: matt.r.willer+boxadmin@gmail.com\nCreated At: '2016-11-16T22:08:08-08:00'\nItem:\n    ID: '987654321'\n    Type: file\nModified At: '2016-11-16T22:08:08-08:00'\n"
  },
  {
    "path": "test/fixtures/output/comments_get_yaml.txt",
    "content": "Type: comment\nID: '123456789'\nIs Reply Comment: false\nMessage: Looks good!\nCreated By:\n    Type: user\n    ID: '9078563412'\n    Name: Commenting User\n    Login: comments@example.com\nCreated At: '2016-11-16T22:03:56-08:00'\nItem:\n    ID: '987654321'\n    Type: file\nModified At: '2016-11-16T22:03:56-08:00'\n"
  },
  {
    "path": "test/fixtures/output/comments_list_json.txt",
    "content": "[\n    {\n        \"type\": \"comment\",\n        \"id\": \"111111\",\n        \"is_reply_comment\": false,\n        \"message\": \"Hello Nadal\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"274664201\",\n            \"name\": \"Roger Federer\",\n            \"login\": \"roger.federer@example.com\"\n        },\n        \"created_at\": \"2018-06-06T13:18:08-07:00\"\n    },\n    {\n        \"type\": \"comment\",\n        \"id\": \"222222\",\n        \"is_reply_comment\": false,\n        \"message\": \"Hello Roger\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"274664201\",\n            \"name\": \"Rafa Nadal\",\n            \"login\": \"rafa.nadal@example.com\"\n        },\n        \"created_at\": \"2018-06-06T13:18:22-07:00\"\n    },\n    {\n        \"type\": \"comment\",\n        \"id\": \"1111111\",\n        \"is_reply_comment\": false,\n        \"message\": \"Hello Nadal\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"274664201\",\n            \"name\": \"Roger Federer\",\n            \"login\": \"roger.federer@example.com\"\n        },\n        \"created_at\": \"2018-06-06T13:18:08-07:00\"\n    },\n    {\n        \"type\": \"comment\",\n        \"id\": \"2222222\",\n        \"is_reply_comment\": false,\n        \"message\": \"Hello Roger\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"274664201\",\n            \"name\": \"Rafa Nadal\",\n            \"login\": \"rafa.nadal@example.com\"\n        },\n        \"created_at\": \"2018-06-06T13:18:22-07:00\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/comments_reply_yaml.txt",
    "content": "Type: comment\nID: '191969'\nIs Reply Comment: true\nMessage: These tigers are cool!\nCreated By:\n    Type: user\n    ID: '17738362'\n    Name: sean rose\n    Login: sean@example.com\nCreated At: '2012-12-12T11:25:01-08:00'\nItem:\n    ID: '5000948880'\n    Type: comment\nModified At: '2012-12-12T11:25:01-08:00'\n"
  },
  {
    "path": "test/fixtures/output/comments_update_yaml.txt",
    "content": "Type: comment\nID: '123456789'\nIs Reply Comment: false\nMessage: Looks great!\nCreated By:\n    Type: user\n    ID: '9078563412'\n    Name: Commenting User\n    Login: comments@example.com\nCreated At: '2016-11-16T22:03:56-08:00'\nItem:\n    ID: '987654321'\n    Type: file\nModified At: '2016-11-16T22:03:56-08:00'\n"
  },
  {
    "path": "test/fixtures/output/device_pins_get_yaml.txt",
    "content": "Type: device_pinner\nID: '123456789'\nOwned By:\n    Type: user\n    ID: '987654321'\n    Name: Device User\n    Login: iphone@example.com\nProduct Name: iPhone\nCreated At: '2016-11-16T19:05:05-08:00'\nModified At: '2016-11-16T19:05:05-08:00'\n"
  },
  {
    "path": "test/fixtures/output/device_pins_list_json.txt",
    "content": "[\n    {\n        \"type\": \"device_pinner\",\n        \"id\": \"788804\",\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"222276603\",\n            \"name\": \"Ted Blosser\",\n            \"login\": \"ted+boxworks2@example.com\"\n        },\n        \"product_name\": \"iPad\"\n    },\n    {\n        \"type\": \"device_pinner\",\n        \"id\": \"1003086\",\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"222276603\",\n            \"name\": \"Ted Blosser\",\n            \"login\": \"ted+boxworks2@example.com\"\n        },\n        \"product_name\": \"iPhone\"\n    },\n    {\n        \"type\": \"device_pinner\",\n        \"id\": \"788803\",\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"222276603\",\n            \"name\": \"Ted Blosser\",\n            \"login\": \"ted+boxworks2@example.com\"\n        },\n        \"product_name\": \"iPad\"\n    },\n    {\n        \"type\": \"device_pinner\",\n        \"id\": \"1003082\",\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"222276603\",\n            \"name\": \"Ted Blosser\",\n            \"login\": \"ted+boxworks2@example.com\"\n        },\n        \"product_name\": \"iPhone\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/events_get_json.txt",
    "content": "[\n    {\n        \"source\": {\n            \"type\": \"user\",\n            \"id\": \"222853849\",\n            \"name\": \"Nick Lee\",\n            \"login\": \"nlee+demo4@example.com\"\n        },\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"222853849\",\n            \"name\": \"sean rose\",\n            \"login\": \"sean+awesome@example.com\"\n        },\n        \"created_at\": \"2015-12-02T09:41:31-08:00\",\n        \"event_id\": \"b9a2393a-20cf-4307-90f5-004110dec209\",\n        \"event_type\": \"ADD_LOGIN_ACTIVITY_DEVICE\",\n        \"ip_address\": \"Unknown IP\",\n        \"type\": \"event\",\n        \"session_id\": null,\n        \"additional_details\": null\n    },\n    {\n        \"source\": {\n            \"type\": \"user\",\n            \"id\": \"222853849\",\n            \"name\": \"sean rose\",\n            \"login\": \"sean+awesome@example.com\"\n        },\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"222853849\",\n            \"name\": \"Nick Lee\",\n            \"login\": \"nlee+demo4@example.com\"\n        },\n        \"created_at\": \"2015-12-02T09:41:31-08:00\",\n        \"event_id\": \"1a4ade15-b1ff-4cc3-89a8-955e1522557c\",\n        \"event_type\": \"LOGIN\",\n        \"ip_address\": \"Unknown IP\",\n        \"type\": \"event\",\n        \"session_id\": null,\n        \"additional_details\": null\n    },\n    {\n        \"source\": {\n            \"type\": \"user\",\n            \"id\": \"11111\",\n            \"name\": \"Example User\",\n            \"login\": \"user@example.com\"\n        },\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"22222\",\n            \"name\": \"Example User 2\",\n            \"login\": \"user2@example.com\"\n        },\n        \"created_at\": \"2015-12-02T09:41:31-08:00\",\n        \"event_id\": \"492264c1-deb5-49a4-850f-78411c30bce4\",\n        \"event_type\": \"ADD_LOGIN_ACTIVITY_DEVICE\",\n        \"ip_address\": \"Unknown IP\",\n        \"type\": \"event\",\n        \"session_id\": null,\n        \"additional_details\": null\n    },\n    {\n        \"source\": {\n            \"type\": \"user\",\n            \"id\": \"22222\",\n            \"name\": \"Example User 2\",\n            \"login\": \"user2@example.com\"\n        },\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"11111\",\n            \"name\": \"Example User\",\n            \"login\": \"user@example.com\"\n        },\n        \"created_at\": \"2015-12-02T09:41:31-08:00\",\n        \"event_id\": \"157c49ab-03b7-4ed1-a49c-82fb93ae558c\",\n        \"event_type\": \"LOGIN\",\n        \"ip_address\": \"Unknown IP\",\n        \"type\": \"event\",\n        \"session_id\": null,\n        \"additional_details\": null\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/file_requests_copy_yaml.txt",
    "content": "ID: 42037322\nType: file_request\nCreated At: '2020-09-28T10:53:43-08:00'\nCreated By:\n    ID: 11446498\n    Type: user\n    Login: ceo@example.com\n    Name: Aaron Levie\nDescription: Following documents are requested for your process\nETag: 1\nExpires At: '2020-09-28T10:53:43-08:00'\nFolder:\n    ID: 12345\n    Type: folder\n    ETag: 1\n    Name: Contracts\n    Sequence ID: 3\nIs Description Required: true\nIs Email Required: true\nStatus: active\nTitle: Please upload documents\nUpdated At: '2020-09-28T10:53:43-08:00'\nUpdated By:\n    ID: 11446498\n    Type: user\n    Login: ceo@example.com\n    Name: Aaron Levie\nURL: /f/19e57f40ace247278a8e3d336678c64a\n"
  },
  {
    "path": "test/fixtures/output/file_requests_get_yaml.txt",
    "content": "ID: 42037322\nType: file_request\nCreated At: '2020-09-28T10:53:43-08:00'\nCreated By:\n    ID: 11446498\n    Type: user\n    Login: ceo@example.com\n    Name: Aaron Levie\nDescription: Following documents are requested for your process\nETag: 1\nExpires At: '2020-09-28T10:53:43-08:00'\nFolder:\n    ID: 12345\n    Type: folder\n    ETag: 1\n    Name: Contracts\n    Sequence ID: 3\nIs Description Required: true\nIs Email Required: true\nStatus: active\nTitle: Please upload documents\nUpdated At: '2020-09-28T10:53:43-08:00'\nUpdated By:\n    ID: 11446498\n    Type: user\n    Login: ceo@example.com\n    Name: Aaron Levie\nURL: /f/19e57f40ace247278a8e3d336678c64a\n"
  },
  {
    "path": "test/fixtures/output/file_requests_update_yaml.txt",
    "content": "ID: 42037322\nType: file_request\nCreated At: '2020-09-28T10:53:43-08:00'\nCreated By:\n    ID: 11446498\n    Type: user\n    Login: ceo@example.com\n    Name: Aaron Levie\nDescription: Following documents are requested for your process\nETag: 1\nExpires At: '2020-09-28T10:53:43-08:00'\nFolder:\n    ID: 12345\n    Type: folder\n    ETag: 1\n    Name: Contracts\n    Sequence ID: 3\nIs Description Required: true\nIs Email Required: true\nStatus: active\nTitle: Please upload documents\nUpdated At: '2020-09-28T10:53:43-08:00'\nUpdated By:\n    ID: 11446498\n    Type: user\n    Login: ceo@example.com\n    Name: Aaron Levie\nURL: /f/19e57f40ace247278a8e3d336678c64a\n"
  },
  {
    "path": "test/fixtures/output/files_collaborations_add_yaml.txt",
    "content": "Type: collaboration\nID: '1234567890'\nCreated By:\n    Type: user\n    ID: '9753108642'\n    Name: Inviting User\n    Login: invites@example.com\nCreated At: '2016-11-16T21:33:31-08:00'\nModified At: '2016-11-16T21:33:31-08:00'\nExpires At: null\nStatus: accepted\nAccessible By:\n    Type: user\n    ID: '987654321'\n    Name: My New Friend\n    Login: newfriend@example.com\nRole: previewer\nAcknowledged At: '2016-11-16T21:33:31-08:00'\nItem:\n    Type: file\n    ID: '1234567890'\n    Sequence ID: '0'\n    ETag: '0'\n    Name: Collaborated File\n"
  },
  {
    "path": "test/fixtures/output/files_collaborations_list_json.txt",
    "content": "[\n    {\n        \"type\": \"collaboration\",\n        \"id\": \"13421432143\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"11111\",\n            \"name\": \"Bob Dylan\",\n            \"login\": \"bob.dylan@gmail.com\"\n        },\n        \"created_at\": \"2018-06-08T11:48:21-07:00\",\n        \"modified_at\": \"2018-06-11T13:03:45-07:00\",\n        \"expires_at\": null,\n        \"status\": \"accepted\",\n        \"accessible_by\": {\n            \"type\": \"user\",\n            \"id\": \"22222\",\n            \"name\": \"Steve Jobs\",\n            \"login\": \"steve.jobs@microsoft.com\"\n        },\n        \"role\": \"editor\",\n        \"acknowledged_at\": \"2018-06-08T11:48:21-07:00\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"1234567890\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"32132131431\",\n                \"sha1\": \"34134214j321h432j14h321\"\n            },\n            \"sequence_id\": \"234\",\n            \"etag\": \"234\",\n            \"sha1\": \"32413h214j32141h32\",\n            \"name\": \"Collab.boxnote\"\n        }\n    },\n    {\n        \"type\": \"collaboration\",\n        \"id\": \"13421432143\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"11111\",\n            \"name\": \"Bob Dylan\",\n            \"login\": \"bob.dylan@gmail.com\"\n        },\n        \"created_at\": \"2018-06-08T11:48:21-07:00\",\n        \"modified_at\": \"2018-06-11T13:03:45-07:00\",\n        \"expires_at\": null,\n        \"status\": \"accepted\",\n        \"accessible_by\": {\n            \"type\": \"user\",\n            \"id\": \"22222\",\n            \"name\": \"Steve Jobs\",\n            \"login\": \"steve.jobs@microsoft.com\"\n        },\n        \"role\": \"editor\",\n        \"acknowledged_at\": \"2018-06-08T11:48:21-07:00\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"1234567890\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"32132131431\",\n                \"sha1\": \"34134214j321h432j14h321\"\n            },\n            \"sequence_id\": \"234\",\n            \"etag\": \"234\",\n            \"sha1\": \"32413h214j32141h32\",\n            \"name\": \"Collab.boxnote\"\n        }\n    },\n    {\n        \"type\": \"collaboration\",\n        \"id\": \"1342143214678\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"11111\",\n            \"name\": \"Bob Dylan\",\n            \"login\": \"bob.dylan@gmail.com\"\n        },\n        \"created_at\": \"2018-06-08T11:48:21-07:00\",\n        \"modified_at\": \"2018-06-11T13:03:45-07:00\",\n        \"expires_at\": null,\n        \"status\": \"accepted\",\n        \"accessible_by\": {\n            \"type\": \"user\",\n            \"id\": \"22222\",\n            \"name\": \"Steve Jobs\",\n            \"login\": \"steve.jobs@microsoft.com\"\n        },\n        \"role\": \"editor\",\n        \"acknowledged_at\": \"2018-06-08T11:48:21-07:00\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"1234567890\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"32132131431\",\n                \"sha1\": \"34134214j321h432j14h321\"\n            },\n            \"sequence_id\": \"234\",\n            \"etag\": \"234\",\n            \"sha1\": \"32413h214j32141h32\",\n            \"name\": \"Collab.boxnote\"\n        }\n    },\n    {\n        \"type\": \"collaboration\",\n        \"id\": \"134214321764\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"11111\",\n            \"name\": \"Bob Dylan\",\n            \"login\": \"bob.dylan@gmail.com\"\n        },\n        \"created_at\": \"2018-06-08T11:48:21-07:00\",\n        \"modified_at\": \"2018-06-11T13:03:45-07:00\",\n        \"expires_at\": null,\n        \"status\": \"accepted\",\n        \"accessible_by\": {\n            \"type\": \"user\",\n            \"id\": \"22222\",\n            \"name\": \"Steve Jobs\",\n            \"login\": \"steve.jobs@microsoft.com\"\n        },\n        \"role\": \"editor\",\n        \"acknowledged_at\": \"2018-06-08T11:48:21-07:00\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"1234567890\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"32132131431\",\n                \"sha1\": \"34134214j321h432j14h321\"\n            },\n            \"sequence_id\": \"234\",\n            \"etag\": \"234\",\n            \"sha1\": \"32413h214j32141h32\",\n            \"name\": \"Collab.boxnote\"\n        }\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/files_copy_yaml.txt",
    "content": "Type: file\nID: '1234567890'\nFile Version:\n    Type: file_version\n    ID: '11223344556677'\n    SHA1: 97b3dbba6eab7ad0f058240744c8636b7c7bea93\nSequence ID: '2'\nETag: '2'\nSHA1: 97b3dbba6eab7ad0f058240744c8636b7c7bea93\nName: Dog.png\nDescription: ''\nSize: 106833\nPath Collection:\n    Total Count: 2\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\n        -\n            Type: folder\n            ID: '987654321'\n            Sequence ID: '0'\n            ETag: '0'\n            Name: Collaborated Folder\nCreated At: '2016-11-16T22:01:44-08:00'\nModified At: '2016-11-16T23:23:57-08:00'\nTrashed At: null\nPurged At: null\nContent Created At: '2016-10-29T18:33:50-07:00'\nContent Modified At: '2016-10-29T18:33:50-07:00'\nCreated By:\n    Type: user\n    ID: '1357924680'\n    Name: Owner\n    Login: owner@example.com\nModified By:\n    Type: user\n    ID: '1357924680'\n    Name: Owner\n    Login: owner@example.com\nOwned By:\n    Type: user\n    ID: '1357924680'\n    Name: Owner\n    Login: owner@example.com\nShared Link: null\nParent:\n    Type: folder\n    ID: '987654321'\n    Sequence ID: '0'\n    ETag: '0'\n    Name: Collaborated Folder\nItem Status: active\n"
  },
  {
    "path": "test/fixtures/output/files_get_yaml.txt",
    "content": "Type: file\nID: '1234567890'\nFile Version:\n    Type: file_version\n    ID: '11223344556677'\n    SHA1: 97b3dbba6eab7ad0f058240744c8636b7c7bea93\nSequence ID: '1'\nETag: '1'\nSHA1: 97b3dbba6eab7ad0f058240744c8636b7c7bea93\nName: test_file_download.txt\nDescription: ''\nSize: 295191\nPath Collection:\n    Total Count: 2\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\n        -\n            Type: folder\n            ID: '987654321'\n            Sequence ID: '0'\n            ETag: '0'\n            Name: Collaborated Folder\nCreated At: '2016-11-16T22:01:44-08:00'\nModified At: '2016-11-16T22:01:51-08:00'\nTrashed At: null\nPurged At: null\nContent Created At: '2016-10-29T18:33:50-07:00'\nContent Modified At: '2016-10-29T18:33:50-07:00'\nCreated By:\n    Type: user\n    ID: '1357924680'\n    Name: Owner\n    Login: owner@example.com\nModified By:\n    Type: user\n    ID: '1357924680'\n    Name: Owner\n    Login: owner@example.com\nOwned By:\n    Type: user\n    ID: '1357924680'\n    Name: Owner\n    Login: owner@example.com\nShared Link: null\nParent:\n    Type: folder\n    ID: '987654321'\n    Sequence ID: '0'\n    ETag: '0'\n    Name: Collaborated Folder\nItem Status: active\n"
  },
  {
    "path": "test/fixtures/output/files_lock_yaml.txt",
    "content": "Type: file\nID: '1234567890'\nFile Version:\n    Type: file_version\n    ID: '22222'\n    SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\nSequence ID: '0'\nETag: '0'\nSHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\nName: Lock file.txt\nDescription: ''\nSize: 9\nPath Collection:\n    Total Count: 1\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\nCreated At: '2016-12-07T15:56:54-08:00'\nModified At: '2016-12-07T15:56:54-08:00'\nTrashed At: null\nPurged At: null\nContent Created At: '2016-12-07T15:53:59-08:00'\nContent Modified At: '2016-12-07T15:53:59-08:00'\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nModified By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nOwned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nShared Link: null\nParent:\n    Type: folder\n    ID: '0'\n    Sequence ID: null\n    ETag: null\n    Name: All Files\nItem Status: active\n"
  },
  {
    "path": "test/fixtures/output/files_metadata_create_yaml.txt",
    "content": "test: test123\nnumber: 1.9\n$type: testTemplate-2890e938-874d-4959-bbc7-6a778b3ad75c\n$parent: file_11111\n$id: 89b3a698-7705-3152-9c25-73f789a1b924\n$version: 0\n$typeVersion: 0\n$template: testTemplate\n$scope: enterprise_22222\n"
  },
  {
    "path": "test/fixtures/output/files_metadata_get_all_json.txt",
    "content": "[\n    {\n        \"$type\": \"testTemplate-2890e928-874d-4959-afb7-6a778b3ad75c\",\n        \"$parent\": \"file_11111\",\n        \"$id\": \"ff8cb88e-de80-467c-aa02-412c1cdaee48\",\n        \"$version\": 1,\n        \"$typeVersion\": 0,\n        \"testEnum\": \"foo\",\n        \"$template\": \"testTemplate\",\n        \"$scope\": \"enterprise_22222\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/files_metadata_get_yaml.txt",
    "content": "$type: testTemplate-2890e938-874d-4059-afc7-6a778b3ad75c\n$parent: file_11111\n$id: ff8ab88e-de80-567c-aa02-412c1cdaee36\n$version: 1\n$typeVersion: 0\ntestEnum: foo\n$template: testTemplate\n$scope: enterprise_22222\n"
  },
  {
    "path": "test/fixtures/output/files_metadata_update_yaml.txt",
    "content": "$type: testTemplate-2890e938-874d-4059-afc7-6a778b3ad75c\n$parent: file_11111\n$id: ff8ab88e-de80-567c-aa02-412c1cdaee36\n$version: 1\n$typeVersion: 0\ntestEnum: foo\n$template: testTemplate\n$scope: enterprise_22222\n"
  },
  {
    "path": "test/fixtures/output/files_move_yaml.txt",
    "content": "Type: file\nID: '1234567890'\nFile Version:\n    Type: file_version\n    ID: '11223344556677'\n    SHA1: 97b3dbba6eab7ad0f058240744c8636b7c7bea93\nSequence ID: '2'\nETag: '2'\nSHA1: 97b3dbba6eab7ad0f058240744c8636b7c7bea93\nName: test\nDescription: test_description\nSize: 106833\nPath Collection:\n    Total Count: 2\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\n        -\n            Type: folder\n            ID: '987654321'\n            Sequence ID: '0'\n            ETag: '0'\n            Name: Collaborated Folder\nCreated At: '2016-11-16T22:01:44-08:00'\nModified At: '2016-11-16T23:23:57-08:00'\nTrashed At: null\nPurged At: null\nContent Created At: '2016-10-29T18:33:50-07:00'\nContent Modified At: '2016-10-29T18:33:50-07:00'\nCreated By:\n    Type: user\n    ID: '1357924680'\n    Name: Owner\n    Login: owner@example.com\nModified By:\n    Type: user\n    ID: '1357924680'\n    Name: Owner\n    Login: owner@example.com\nOwned By:\n    Type: user\n    ID: '1357924680'\n    Name: Owner\n    Login: owner@example.com\nShared Link: null\nParent:\n    Type: folder\n    ID: '987654321'\n    Sequence ID: '0'\n    ETag: '0'\n    Name: Collaborated Folder\nItem Status: active\n"
  },
  {
    "path": "test/fixtures/output/files_rename_yaml.txt",
    "content": "Type: file\nID: '1234567890'\nFile Version:\n    Type: file_version\n    ID: '11223344556677'\n    SHA1: 97b3dbba6eab7ad0f058240744c8636b7c7bea93\nSequence ID: '2'\nETag: '2'\nSHA1: 97b3dbba6eab7ad0f058240744c8636b7c7bea93\nName: test\nDescription: test_description\nSize: 106833\nPath Collection:\n    Total Count: 2\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\n        -\n            Type: folder\n            ID: '987654321'\n            Sequence ID: '0'\n            ETag: '0'\n            Name: Collaborated Folder\nCreated At: '2016-11-16T22:01:44-08:00'\nModified At: '2016-11-16T23:23:57-08:00'\nTrashed At: null\nPurged At: null\nContent Created At: '2016-10-29T18:33:50-07:00'\nContent Modified At: '2016-10-29T18:33:50-07:00'\nCreated By:\n    Type: user\n    ID: '1357924680'\n    Name: Owner\n    Login: owner@example.com\nModified By:\n    Type: user\n    ID: '1357924680'\n    Name: Owner\n    Login: owner@example.com\nOwned By:\n    Type: user\n    ID: '1357924680'\n    Name: Owner\n    Login: owner@example.com\nShared Link: null\nParent:\n    Type: folder\n    ID: '987654321'\n    Sequence ID: '0'\n    ETag: '0'\n    Name: Collaborated Folder\nItem Status: active\n"
  },
  {
    "path": "test/fixtures/output/files_share_json.txt",
    "content": "{\n    \"type\": \"file\",\n    \"id\": \"1234567890\",\n    \"shared_link\": {\n        \"url\": \"https://blosserdemoaccount.box.com/s/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p\",\n        \"download_url\": \"https://blosserdemoaccount.box.com/shared/static/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p.png\",\n        \"vanity_url\": \"https://app.box.com/v/my-custom-name-123\",\n        \"effective_access\": \"open\",\n        \"is_password_enabled\": true,\n        \"unshared_at\": null,\n        \"download_count\": 0,\n        \"preview_count\": 0,\n        \"access\": \"test\",\n        \"permissions\": {\n            \"can_download\": true,\n            \"can_preview\": true,\n            \"can_edit\": true\n        }\n    }\n}\n"
  },
  {
    "path": "test/fixtures/output/files_share_yaml.txt",
    "content": "Type: file\nID: '1234567890'\nShared Link:\n    URL: https://blosserdemoaccount.box.com/s/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p\n    Download URL: >-\n        https://blosserdemoaccount.box.com/shared/static/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p.png\n    Vanity URL: https://app.box.com/v/my-custom-name-123\n    Effective Access: open\n    Is Password Enabled: true\n    Unshared At: null\n    Download Count: 0\n    Preview Count: 0\n    Access: test\n    Permissions:\n        Can Download: true\n        Can Preview: true\n        Can Edit: true\n"
  },
  {
    "path": "test/fixtures/output/files_tasks_list_json.txt",
    "content": "[\n    {\n        \"type\": \"task\",\n        \"id\": \"11111\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"1234567890\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"22222\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"Tasks file.txt\"\n        },\n        \"due_at\": null\n    },\n    {\n        \"type\": \"task\",\n        \"id\": \"111112\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"1234567890\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"22222\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"Tasks file.txt\"\n        },\n        \"due_at\": null\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/files_unlock_yaml.txt",
    "content": "Type: file\nID: '1234567890'\nFile Version:\n    Type: file_version\n    ID: '22222'\n    SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\nSequence ID: '0'\nETag: '0'\nSHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\nName: Lock file.txt\nDescription: ''\nSize: 9\nPath Collection:\n    Total Count: 1\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\nCreated At: '2016-12-07T15:56:54-08:00'\nModified At: '2016-12-07T15:56:54-08:00'\nTrashed At: null\nPurged At: null\nContent Created At: '2016-12-07T15:53:59-08:00'\nContent Modified At: '2016-12-07T15:53:59-08:00'\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nModified By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nOwned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nShared Link: null\nParent:\n    Type: folder\n    ID: '0'\n    Sequence ID: null\n    ETag: null\n    Name: All Files\nItem Status: active\n"
  },
  {
    "path": "test/fixtures/output/files_upload_json.txt",
    "content": "{\n    \"type\": \"file\",\n    \"id\": \"1234567890\",\n    \"file_version\": {\n        \"type\": \"file_version\",\n        \"id\": \"098765432109\",\n        \"sha1\": \"0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33\"\n    },\n    \"sequence_id\": \"0\",\n    \"etag\": \"0\",\n    \"sha1\": \"0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33\",\n    \"name\": \"file.txt\",\n    \"description\": \"\",\n    \"size\": 3,\n    \"path_collection\": {\n        \"total_count\": 1,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            }\n        ]\n    },\n    \"created_at\": \"2017-05-16T15:18:02-07:00\",\n    \"modified_at\": \"2017-05-16T15:18:02-07:00\",\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": \"2017-05-16T15:18:02-07:00\",\n    \"content_modified_at\": \"2017-05-16T15:18:02-07:00\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"123456789\",\n        \"name\": \"Test User\",\n        \"login\": \"test@example.com\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"123456789\",\n        \"name\": \"Test User\",\n        \"login\": \"test@example.com\"\n    },\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"123456789\",\n        \"name\": \"Test User\",\n        \"login\": \"test@example.com\"\n    },\n    \"shared_link\": null,\n    \"parent\": {\n        \"type\": \"user\",\n        \"id\": \"123456789\",\n        \"name\": \"Test User\",\n        \"login\": \"test@example.com\"\n    },\n    \"item_status\": \"active\"\n}\n"
  },
  {
    "path": "test/fixtures/output/files_upload_yaml.txt",
    "content": "Type: file\nID: '1234567890'\nFile Version:\n    Type: file_version\n    ID: '098765432109'\n    SHA1: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33\nSequence ID: '0'\nETag: '0'\nSHA1: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33\nName: file.txt\nDescription: ''\nSize: 3\nPath Collection:\n    Total Count: 1\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\nCreated At: '2017-05-16T15:18:02-07:00'\nModified At: '2017-05-16T15:18:02-07:00'\nTrashed At: null\nPurged At: null\nContent Created At: '2017-05-16T15:18:02-07:00'\nContent Modified At: '2017-05-16T15:18:02-07:00'\nCreated By:\n    Type: user\n    ID: '123456789'\n    Name: Test User\n    Login: test@example.com\nModified By:\n    Type: user\n    ID: '123456789'\n    Name: Test User\n    Login: test@example.com\nOwned By:\n    Type: user\n    ID: '123456789'\n    Name: Test User\n    Login: test@example.com\nShared Link: null\nParent:\n    Type: user\n    ID: '123456789'\n    Name: Test User\n    Login: test@example.com\nItem Status: active\n"
  },
  {
    "path": "test/fixtures/output/files_versions_list_json.txt",
    "content": "[\n    {\n        \"type\": \"file_version\",\n        \"id\": \"11111\",\n        \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n        \"name\": \"test file.txt\",\n        \"size\": 16,\n        \"created_at\": \"2016-12-07T15:59:32-08:00\",\n        \"modified_at\": \"2016-12-07T15:59:32-08:00\",\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"trashed_at\": null,\n        \"purged_at\": null\n    },\n    {\n        \"type\": \"file_version\",\n        \"id\": \"22222\",\n        \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n        \"name\": \"test file.txt\",\n        \"size\": 9,\n        \"created_at\": \"2016-12-07T15:53:59-08:00\",\n        \"modified_at\": \"2016-12-07T15:53:59-08:00\",\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"trashed_at\": null,\n        \"purged_at\": null\n    },\n    {\n        \"type\": \"file_version\",\n        \"id\": \"111112\",\n        \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n        \"name\": \"test file.txt\",\n        \"size\": 16,\n        \"created_at\": \"2016-12-07T15:59:32-08:00\",\n        \"modified_at\": \"2016-12-07T15:59:32-08:00\",\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"trashed_at\": null,\n        \"purged_at\": null\n    },\n    {\n        \"type\": \"file_version\",\n        \"id\": \"222223\",\n        \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n        \"name\": \"test file.txt\",\n        \"size\": 9,\n        \"created_at\": \"2016-12-07T15:53:59-08:00\",\n        \"modified_at\": \"2016-12-07T15:53:59-08:00\",\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"trashed_at\": null,\n        \"purged_at\": null\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/files_versions_list_pagination_json.txt",
    "content": "[\n    {\n        \"type\": \"file_version\",\n        \"id\": \"11111\",\n        \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n        \"name\": \"test file.txt\",\n        \"size\": 16,\n        \"created_at\": \"2016-12-07T15:59:32-08:00\",\n        \"modified_at\": \"2016-12-07T15:59:32-08:00\",\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"trashed_at\": null,\n        \"purged_at\": null\n    },\n    {\n        \"type\": \"file_version\",\n        \"id\": \"22222\",\n        \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n        \"name\": \"test file.txt\",\n        \"size\": 9,\n        \"created_at\": \"2016-12-07T15:53:59-08:00\",\n        \"modified_at\": \"2016-12-07T15:53:59-08:00\",\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"trashed_at\": null,\n        \"purged_at\": null\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/files_versions_promote_yaml.txt",
    "content": "Type: file_version\nID: '1234567890'\nSHA1: 97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\nName: test file.txt\nSize: 16\nCreated At: '2018-04-24T15:08:58-07:00'\nModified At: '2018-04-24T15:08:58-07:00'\nModified By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nTrashed At: null\nPurged At: null\n"
  },
  {
    "path": "test/fixtures/output/files_versions_upload_json.txt",
    "content": "{\n    \"type\": \"file\",\n    \"id\": \"1234567890\",\n    \"file_version\": {\n        \"type\": \"file_version\",\n        \"id\": \"098765432109\",\n        \"sha1\": \"0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33\"\n    },\n    \"sequence_id\": \"0\",\n    \"etag\": \"0\",\n    \"sha1\": \"0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33\",\n    \"name\": \"file.txt\",\n    \"description\": \"\",\n    \"size\": 3,\n    \"path_collection\": {\n        \"total_count\": 1,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            }\n        ]\n    },\n    \"created_at\": \"2017-05-16T15:18:02-07:00\",\n    \"modified_at\": \"2017-05-16T15:18:02-07:00\",\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": \"2017-05-16T15:18:02-07:00\",\n    \"content_modified_at\": \"2017-05-16T15:18:02-07:00\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"123456789\",\n        \"name\": \"Test User\",\n        \"login\": \"test@example.com\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"123456789\",\n        \"name\": \"Test User\",\n        \"login\": \"test@example.com\"\n    },\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"123456789\",\n        \"name\": \"Test User\",\n        \"login\": \"test@example.com\"\n    },\n    \"shared_link\": null,\n    \"parent\": {\n        \"type\": \"user\",\n        \"id\": \"123456789\",\n        \"name\": \"Test User\",\n        \"login\": \"test@example.com\"\n    },\n    \"item_status\": \"active\"\n}\n"
  },
  {
    "path": "test/fixtures/output/files_versions_upload_yaml.txt",
    "content": "Type: file\nID: '1234567890'\nFile Version:\n    Type: file_version\n    ID: '098765432109'\n    SHA1: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33\nSequence ID: '0'\nETag: '0'\nSHA1: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33\nName: file.txt\nDescription: ''\nSize: 3\nPath Collection:\n    Total Count: 1\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\nCreated At: '2017-05-16T15:18:02-07:00'\nModified At: '2017-05-16T15:18:02-07:00'\nTrashed At: null\nPurged At: null\nContent Created At: '2017-05-16T15:18:02-07:00'\nContent Modified At: '2017-05-16T15:18:02-07:00'\nCreated By:\n    Type: user\n    ID: '123456789'\n    Name: Test User\n    Login: test@example.com\nModified By:\n    Type: user\n    ID: '123456789'\n    Name: Test User\n    Login: test@example.com\nOwned By:\n    Type: user\n    ID: '123456789'\n    Name: Test User\n    Login: test@example.com\nShared Link: null\nParent:\n    Type: user\n    ID: '123456789'\n    Name: Test User\n    Login: test@example.com\nItem Status: active\n"
  },
  {
    "path": "test/fixtures/output/folders_collaborations_add_yaml.txt",
    "content": "Type: collaboration\nID: '1234567890'\nCreated By:\n    Type: user\n    ID: '9753108642'\n    Name: Inviting User\n    Login: invites@example.com\nCreated At: '2016-11-16T21:33:31-08:00'\nModified At: '2016-11-16T21:33:31-08:00'\nExpires At: null\nStatus: accepted\nAccessible By:\n    Type: user\n    ID: '987654321'\n    Name: My New Friend\n    Login: newfriend@example.com\nRole: previewer\nAcknowledged At: '2016-11-16T21:33:31-08:00'\nItem:\n    Type: folder\n    ID: '0'\n    Sequence ID: '0'\n    ETag: '0'\n    Name: Collaborated Folder\n"
  },
  {
    "path": "test/fixtures/output/folders_collaborations_list_json.txt",
    "content": "[\n    {\n        \"type\": \"collaboration\",\n        \"id\": \"12345\",\n        \"created_by\": null,\n        \"created_at\": \"2016-11-16T21:48:44-08:00\",\n        \"modified_at\": \"2016-11-16T21:48:44-08:00\",\n        \"expires_at\": null,\n        \"status\": \"accepted\",\n        \"accessible_by\": {\n            \"type\": \"group\",\n            \"id\": \"22222\",\n            \"name\": \"Employees\",\n            \"group_type\": \"managed_group\"\n        },\n        \"role\": \"editor\",\n        \"acknowledged_at\": \"2016-11-16T21:48:44-08:00\",\n        \"item\": {\n            \"type\": \"folder\",\n            \"id\": \"0\",\n            \"sequence_id\": \"1\",\n            \"etag\": \"1\",\n            \"name\": \"Collab Folder\"\n        }\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/folders_copy_yaml.txt",
    "content": "Type: folder\nID: '0'\nSequence ID: '0'\nETag: '0'\nName: New Folder (1)\nCreated At: '2018-04-25T13:18:21-07:00'\nModified At: '2018-04-25T13:18:21-07:00'\nDescription: ''\nSize: 0\nPath Collection:\n    Total Count: 1\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nModified By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nTrashed At: null\nPurged At: null\nContent Created At: '2018-04-25T13:18:21-07:00'\nContent Modified At: '2018-04-25T13:18:21-07:00'\nOwned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nShared Link: null\nFolder Upload Email: null\nParent:\n    Type: folder\n    ID: '987654321'\n    Sequence ID: null\n    ETag: null\n    Name: All Files\nItem Status: active\nItem Collection:\n    Total Count: 0\n    Entries: []\n    Offset: 0\n    Limit: 100\n    Order:\n        -\n            By: type\n            Direction: ASC\n        -\n            By: name\n            Direction: ASC\n"
  },
  {
    "path": "test/fixtures/output/folders_create_yaml.txt",
    "content": "Type: folder\nID: '22222'\nSequence ID: '0'\nETag: '0'\nName: New Folder\nCreated At: '2018-04-25T13:11:51-07:00'\nModified At: '2018-04-25T13:11:51-07:00'\nDescription: ''\nSize: 0\nPath Collection:\n    Total Count: 1\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nModified By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nTrashed At: null\nPurged At: null\nContent Created At: '2018-04-25T13:11:51-07:00'\nContent Modified At: '2018-04-25T13:11:51-07:00'\nOwned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nShared Link: null\nFolder Upload Email: null\nParent:\n    Type: folder\n    ID: '0'\n    Sequence ID: null\n    ETag: null\n    Name: All Files\nItem Status: active\nItem Collection:\n    Total Count: 0\n    Entries: []\n    Offset: 0\n    Limit: 100\n    Order:\n        -\n            By: type\n            Direction: ASC\n        -\n            By: name\n            Direction: ASC\n"
  },
  {
    "path": "test/fixtures/output/folders_get_yaml.txt",
    "content": "Type: folder\nID: '0'\nSequence ID: null\nETag: null\nName: All Files\nCreated At: null\nModified At: null\nDescription: ''\nSize: 8183737\nPath Collection:\n    Total Count: 0\n    Entries: []\nCreated By:\n    Type: user\n    ID: ''\n    Name: ''\n    Login: ''\nModified By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nTrashed At: null\nPurged At: null\nContent Created At: null\nContent Modified At: null\nOwned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nShared Link: null\nFolder Upload Email: null\nParent: null\nItem Status: active\nItem Collection:\n    Total Count: 6\n    Entries:\n        -\n            Type: folder\n            ID: '44444'\n            Sequence ID: '1'\n            ETag: '1'\n            Name: Collab Folder\n        -\n            Type: folder\n            ID: '55555'\n            Sequence ID: '0'\n            ETag: '0'\n            Name: Copied Folder\n        -\n            Type: folder\n            ID: '66666'\n            Sequence ID: '0'\n            ETag: '0'\n            Name: SDK Test Folder\n        -\n            Type: folder\n            ID: '77777'\n            Sequence ID: '1'\n            ETag: '1'\n            Name: Test Folder\n        -\n            Type: file\n            ID: '88888'\n            File Version:\n                Type: file_version\n                ID: '888880'\n                SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n            Sequence ID: '0'\n            ETag: '0'\n            SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n            Name: Copied file.txt\n        -\n            Type: file\n            ID: '99999'\n            File Version:\n                Type: file_version\n                ID: '999990'\n                SHA1: 97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\n            Sequence ID: '9'\n            ETag: '9'\n            SHA1: 97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\n            Name: test file.txt\n    Offset: 0\n    Limit: 100\n    Order:\n        -\n            By: type\n            Direction: ASC\n        -\n            By: name\n            Direction: ASC\n"
  },
  {
    "path": "test/fixtures/output/folders_list_items_json.txt",
    "content": "[\n    {\n        \"type\": \"folder\",\n        \"id\": \"11111\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"name\": \"Collab Folder\"\n    },\n    {\n        \"type\": \"folder\",\n        \"id\": \"22222\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"Copied Folder\"\n    },\n    {\n        \"type\": \"folder\",\n        \"id\": \"33333\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"SDK Test Folder\"\n    },\n    {\n        \"type\": \"folder\",\n        \"id\": \"44444\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"name\": \"Test Folder\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"55555\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"555550\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n        },\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n        \"name\": \"Copied file.txt\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"66666\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"666660\",\n            \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n        },\n        \"sequence_id\": \"9\",\n        \"etag\": \"9\",\n        \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n        \"name\": \"test file.txt\"\n    },\n    {\n        \"type\": \"folder\",\n        \"id\": \"111112\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"name\": \"Collab Folder\"\n    },\n    {\n        \"type\": \"folder\",\n        \"id\": \"222223\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"Copied Folder\"\n    },\n    {\n        \"type\": \"folder\",\n        \"id\": \"33333\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"SDK Test Folder\"\n    },\n    {\n        \"type\": \"folder\",\n        \"id\": \"444445\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"name\": \"Test Folder\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"55555\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"555550\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n        },\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n        \"name\": \"Copied file.txt\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"66666\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"666660\",\n            \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n        },\n        \"sequence_id\": \"9\",\n        \"etag\": \"9\",\n        \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n        \"name\": \"test file.txt\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/folders_list_items_pagination_json.txt",
    "content": "[\n    {\n        \"type\": \"folder\",\n        \"id\": \"11111\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"SDK Test Folder\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"22222\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"222220\",\n            \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n        },\n        \"sequence_id\": \"9\",\n        \"etag\": \"9\",\n        \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n        \"name\": \"test file.txt\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/folders_list_items_pagination_one_item_json.txt",
    "content": "[\n    {\n        \"type\": \"folder\",\n        \"id\": \"11111\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"SDK Test Folder\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/folders_locks_list_json.txt",
    "content": "[\n    {\n        \"folder\": {\n            \"id\": \"12345\",\n            \"etag\": \"1\",\n            \"type\": \"folder\",\n            \"sequence_id\": \"3\",\n            \"name\": \"Contracts\"\n        },\n        \"id\": \"12345678\",\n        \"type\": \"folder_lock\",\n        \"created_by\": {\n            \"id\": \"11446498\",\n            \"type\": \"user\"\n        },\n        \"created_at\": \"2020-09-14T23:12:53Z\",\n        \"locked_operations\": {\n            \"move\": true,\n            \"delete\": true\n        },\n        \"lock_type\": \"freeze\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/folders_metadata_create_yaml.txt",
    "content": "$type: testTemplate-2890e938-874d-4059-afc7-6a778b3ad75c\n$parent: folder_11111\n$id: ff8ab88e-de80-567c-aa02-412c1cdaee36\n$version: 1\n$typeVersion: 0\ntestEnum: foo\n$template: testTemplate\n$scope: enterprise_22222\n"
  },
  {
    "path": "test/fixtures/output/folders_metadata_get_all_json.txt",
    "content": "[\n    {\n        \"$type\": \"testTemplate-2890e928-874d-4959-afb7-6a778b3ad75c\",\n        \"$parent\": \"folder_11111\",\n        \"$id\": \"ff8cb88e-de80-467c-aa02-412c1cdaee48\",\n        \"$version\": 1,\n        \"$typeVersion\": 0,\n        \"testEnum\": \"foo\",\n        \"$template\": \"testTemplate\",\n        \"$scope\": \"enterprise_22222\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/folders_metadata_get_yaml.txt",
    "content": "$type: testTemplate-2890e938-874d-4059-afc7-6a778b3ad75c\n$parent: folder_11111\n$id: ff8ab88e-de80-567c-aa02-412c1cdaee36\n$version: 1\n$typeVersion: 0\ntestEnum: foo\n$template: testTemplate\n$scope: enterprise_22222\n"
  },
  {
    "path": "test/fixtures/output/folders_metadata_update_yaml.txt",
    "content": "$type: testTemplate-2890e938-874d-4059-afc7-6a778b3ad75c\n$parent: folder_11111\n$id: ff8ab88e-de80-567c-aa02-412c1cdaee36\n$version: 1\n$typeVersion: 0\ntestEnum: foo\n$template: testTemplate\n$scope: enterprise_22222\n"
  },
  {
    "path": "test/fixtures/output/folders_move_yaml.txt",
    "content": "Type: folder\nID: '0'\nSequence ID: '1'\nETag: '1'\nName: New Folder Name\nCreated At: '2018-04-25T13:11:51-07:00'\nModified At: '2018-04-25T14:06:20-07:00'\nDescription: My new folder\nSize: 0\nPath Collection:\n    Total Count: 1\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nModified By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nTrashed At: null\nPurged At: null\nContent Created At: '2018-04-25T13:11:51-07:00'\nContent Modified At: '2018-04-25T14:06:20-07:00'\nOwned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nShared Link: null\nFolder Upload Email: null\nParent:\n    Type: folder\n    ID: '987654321'\n    Sequence ID: null\n    ETag: null\n    Name: All Files\nItem Status: active\nItem Collection:\n    Total Count: 0\n    Entries: []\n    Offset: 0\n    Limit: 100\n    Order:\n        -\n            By: type\n            Direction: ASC\n        -\n            By: name\n            Direction: ASC\n"
  },
  {
    "path": "test/fixtures/output/folders_rename_yaml.txt",
    "content": "Type: folder\nID: '0'\nSequence ID: '1'\nETag: '1'\nName: New Folder Name\nCreated At: '2018-04-25T13:11:51-07:00'\nModified At: '2018-04-25T14:06:20-07:00'\nDescription: My new folder\nSize: 0\nPath Collection:\n    Total Count: 1\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nModified By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nTrashed At: null\nPurged At: null\nContent Created At: '2018-04-25T13:11:51-07:00'\nContent Modified At: '2018-04-25T14:06:20-07:00'\nOwned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nShared Link: null\nFolder Upload Email: null\nParent:\n    Type: folder\n    ID: '987654321'\n    Sequence ID: null\n    ETag: null\n    Name: All Files\nItem Status: active\nItem Collection:\n    Total Count: 0\n    Entries: []\n    Offset: 0\n    Limit: 100\n    Order:\n        -\n            By: type\n            Direction: ASC\n        -\n            By: name\n            Direction: ASC\n"
  },
  {
    "path": "test/fixtures/output/folders_share_json.txt",
    "content": "{\n    \"type\": \"folder\",\n    \"id\": \"0\",\n    \"shared_link\": {\n        \"url\": \"https://blosserdemoaccount.box.com/s/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p\",\n        \"download_url\": \"https://blosserdemoaccount.box.com/shared/static/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p.png\",\n        \"vanity_url\": \"https://app.box.com/v/my-custom-name-123\",\n        \"effective_access\": \"open\",\n        \"is_password_enabled\": true,\n        \"unshared_at\": null,\n        \"download_count\": 0,\n        \"preview_count\": 0,\n        \"access\": \"test\",\n        \"permissions\": {\n            \"can_download\": true,\n            \"can_preview\": true\n        }\n    }\n}\n"
  },
  {
    "path": "test/fixtures/output/folders_share_yaml.txt",
    "content": "Type: folder\nID: '0'\nShared Link:\n    URL: https://blosserdemoaccount.box.com/s/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p\n    Download URL: >-\n        https://blosserdemoaccount.box.com/shared/static/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p.png\n    Vanity URL: https://app.box.com/v/my-custom-name-123\n    Effective Access: open\n    Is Password Enabled: true\n    Unshared At: null\n    Download Count: 0\n    Preview Count: 0\n    Access: test\n    Permissions:\n        Can Download: true\n        Can Preview: true\n"
  },
  {
    "path": "test/fixtures/output/folders_update_yaml.txt",
    "content": "Type: folder\nID: '0'\nSequence ID: '1'\nETag: '1'\nName: New Folder Name\nCreated At: '2018-04-25T13:11:51-07:00'\nModified At: '2018-04-25T14:06:20-07:00'\nDescription: My new folder\nSize: 0\nPath Collection:\n    Total Count: 1\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nModified By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nTrashed At: null\nPurged At: null\nContent Created At: '2018-04-25T13:11:51-07:00'\nContent Modified At: '2018-04-25T14:06:20-07:00'\nOwned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nShared Link: null\nFolder Upload Email: null\nParent:\n    Type: folder\n    ID: '987654321'\n    Sequence ID: null\n    ETag: null\n    Name: All Files\nItem Status: active\nItem Collection:\n    Total Count: 0\n    Entries: []\n    Offset: 0\n    Limit: 100\n    Order:\n        -\n            By: type\n            Direction: ASC\n        -\n            By: name\n            Direction: ASC\n"
  },
  {
    "path": "test/fixtures/output/folders_upload_yaml.txt",
    "content": "Type: folder\nID: '0'\nSequence ID: null\nETag: null\nName: All Files\nCreated At: null\nModified At: null\nDescription: ''\nSize: 8183737\nPath Collection:\n    Total Count: 0\n    Entries: []\nCreated By:\n    Type: user\n    ID: ''\n    Name: ''\n    Login: ''\nModified By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nTrashed At: null\nPurged At: null\nContent Created At: null\nContent Modified At: null\nOwned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nShared Link: null\nFolder Upload Email: null\nParent: null\nItem Status: active\nItem Collection:\n    Total Count: 6\n    Entries:\n        -\n            Type: folder\n            ID: '44444'\n            Sequence ID: '1'\n            ETag: '1'\n            Name: Collab Folder\n        -\n            Type: folder\n            ID: '55555'\n            Sequence ID: '0'\n            ETag: '0'\n            Name: Copied Folder\n        -\n            Type: folder\n            ID: '66666'\n            Sequence ID: '0'\n            ETag: '0'\n            Name: SDK Test Folder\n        -\n            Type: folder\n            ID: '77777'\n            Sequence ID: '1'\n            ETag: '1'\n            Name: Test Folder\n        -\n            Type: file\n            ID: '88888'\n            File Version:\n                Type: file_version\n                ID: '888880'\n                SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n            Sequence ID: '0'\n            ETag: '0'\n            SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n            Name: Copied file.txt\n        -\n            Type: file\n            ID: '99999'\n            File Version:\n                Type: file_version\n                ID: '999990'\n                SHA1: 97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\n            Sequence ID: '9'\n            ETag: '9'\n            SHA1: 97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\n            Name: test file.txt\n    Offset: 0\n    Limit: 100\n    Order:\n        -\n            By: type\n            Direction: ASC\n        -\n            By: name\n            Direction: ASC\n"
  },
  {
    "path": "test/fixtures/output/groups_create_yaml.txt",
    "content": "Type: group\nID: '11111'\nName: Employees\nGroup Type: managed_group\nCreated At: '2018-04-25T15:20:30-07:00'\nModified At: '2018-04-25T15:20:30-07:00'\n"
  },
  {
    "path": "test/fixtures/output/groups_get_yaml.txt",
    "content": "Type: group\nID: '11111'\nName: Employees\nGroup Type: managed_group\nCreated At: '2018-04-25T15:20:30-07:00'\nModified At: '2018-04-25T15:20:30-07:00'\n"
  },
  {
    "path": "test/fixtures/output/groups_list_collaborations_json.txt",
    "content": "[\n    {\n        \"type\": \"group_membership\",\n        \"id\": \"1560354\",\n        \"user\": {\n            \"type\": \"user\",\n            \"id\": \"13130406\",\n            \"name\": \"Alison Wonderland\",\n            \"login\": \"alice@gmail.com\"\n        },\n        \"group\": {\n            \"type\": \"group\",\n            \"id\": \"119720\",\n            \"name\": \"family\"\n        },\n        \"role\": \"member\"\n    },\n    {\n        \"type\": \"group_membership\",\n        \"id\": \"1560353\",\n        \"user\": {\n            \"type\": \"user\",\n            \"id\": \"13130406\",\n            \"name\": \"Alison Wonderland\",\n            \"login\": \"alice2@gmail.com\"\n        },\n        \"group\": {\n            \"type\": \"group\",\n            \"id\": \"119720\",\n            \"name\": \"family\"\n        },\n        \"role\": \"member\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/groups_list_json.txt",
    "content": "[\n    {\n        \"type\": \"group\",\n        \"id\": \"22222\",\n        \"name\": \"Employees\",\n        \"group_type\": \"managed_group\"\n    },\n    {\n        \"type\": \"group\",\n        \"id\": \"11111\",\n        \"name\": \"Remote Employees\",\n        \"group_type\": \"managed_group\"\n    },\n    {\n        \"type\": \"group\",\n        \"id\": \"222223\",\n        \"name\": \"Employees\",\n        \"group_type\": \"managed_group\"\n    },\n    {\n        \"type\": \"group\",\n        \"id\": \"11112\",\n        \"name\": \"Remote Employees\",\n        \"group_type\": \"managed_group\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/groups_membership_add_yaml.txt",
    "content": "Type: group_membership\nID: '12345'\nUser:\n    Type: user\n    ID: '44444'\n    Name: Test User 2\n    Login: testuser2@example.com\nGroup:\n    Type: group\n    ID: '11111'\n    Name: Remote Employees\n    Group Type: managed_group\nRole: admin\nConfigurable Permissions:\n    Can Create Accounts: true\n    Can Edit Accounts: true\n    Can Instant Login: true\n    Can Run Reports: true\nCreated At: '2018-04-25T15:39:35-07:00'\nModified At: '2018-04-25T15:39:35-07:00'\n"
  },
  {
    "path": "test/fixtures/output/groups_membership_get_yaml.txt",
    "content": "Type: group_membership\nID: '12345'\nUser:\n    Type: user\n    ID: '44444'\n    Name: Test User 2\n    Login: testuser2@example.com\nGroup:\n    Type: group\n    ID: '11111'\n    Name: Remote Employees\n    Group Type: managed_group\nRole: admin\nConfigurable Permissions:\n    Can Create Accounts: true\n    Can Edit Accounts: true\n    Can Instant Login: true\n    Can Run Reports: true\nCreated At: '2018-04-25T15:39:35-07:00'\nModified At: '2018-04-25T15:39:35-07:00'\n"
  },
  {
    "path": "test/fixtures/output/groups_membership_list_json.txt",
    "content": "[\n    {\n        \"type\": \"group_membership\",\n        \"id\": \"12345\",\n        \"user\": {\n            \"type\": \"user\",\n            \"id\": \"44444\",\n            \"name\": \"Test User 2\",\n            \"login\": \"testuser2@example.com\"\n        },\n        \"group\": {\n            \"type\": \"group\",\n            \"id\": \"11111\",\n            \"name\": \"Remote Employees\",\n            \"group_type\": \"managed_group\"\n        },\n        \"role\": \"member\"\n    },\n    {\n        \"type\": \"group_membership\",\n        \"id\": \"123456\",\n        \"user\": {\n            \"type\": \"user\",\n            \"id\": \"444445\",\n            \"name\": \"Test User 2\",\n            \"login\": \"testuser2@example.com\"\n        },\n        \"group\": {\n            \"type\": \"group\",\n            \"id\": \"11111\",\n            \"name\": \"Remote Employees\",\n            \"group_type\": \"managed_group\"\n        },\n        \"role\": \"member\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/groups_membership_update_yaml.txt",
    "content": "Type: group_membership\nID: '12345'\nUser:\n    Type: user\n    ID: '44444'\n    Name: Test User 2\n    Login: testuser2@example.com\nGroup:\n    Type: group\n    ID: '11111'\n    Name: Remote Employees\n    Group Type: managed_group\nRole: admin\nConfigurable Permissions:\n    Can Create Accounts: true\n    Can Edit Accounts: true\n    Can Instant Login: true\n    Can Run Reports: true\nCreated At: '2018-04-25T15:39:35-07:00'\nModified At: '2018-04-25T15:39:35-07:00'\n"
  },
  {
    "path": "test/fixtures/output/groups_update_yaml.txt",
    "content": "Type: group\nID: '11111'\nName: Remote Employees\nGroup Type: managed_group\nCreated At: '2018-04-25T15:25:07-07:00'\nModified At: '2018-04-25T15:31:02-07:00'\n"
  },
  {
    "path": "test/fixtures/output/integration_mappings_slack_get_json.txt",
    "content": "[\n    {\n        \"id\": \"123\",\n        \"integration_type\": \"slack\",\n        \"type\": \"integration_mapping\",\n        \"partner_item\": {\n            \"type\": \"channel\",\n            \"id\": \"ABC12378991223\",\n            \"slack_workspace_id\": \"T12352314\",\n            \"slack_org_id\": \"E1234567\"\n        },\n        \"box_item\": {\n            \"id\": \"543\",\n            \"etag\": \"1\",\n            \"type\": \"folder\",\n            \"name\": \"Contracts\",\n            \"sequence_id\": \"3\"\n        },\n        \"is_manually_created\": true,\n        \"options\": {},\n        \"created_by\": {\n            \"id\": \"11446498\",\n            \"type\": \"user\",\n            \"name\": \"Aaron Levie\",\n            \"login\": \"ceo@example.com\"\n        },\n        \"modified_by\": {\n            \"id\": \"11446498\",\n            \"type\": \"user\",\n            \"name\": \"Aaron Levie\",\n            \"login\": \"ceo@example.com\"\n        },\n        \"created_at\": \"2012-12-12T10:53:43-08:00\",\n        \"modified_at\": \"2012-12-12T10:53:43-08:00\"\n    },\n    {\n        \"id\": \"456\",\n        \"integration_type\": \"slack\",\n        \"type\": \"integration_mapping\",\n        \"partner_item\": {\n            \"type\": \"channel\",\n            \"id\": \"XYZ378991223\",\n            \"slack_workspace_id\": \"T12352314\",\n            \"slack_org_id\": \"E1234567\"\n        },\n        \"box_item\": {\n            \"id\": \"987\",\n            \"etag\": \"1\",\n            \"type\": \"folder\",\n            \"name\": \"Contracts\",\n            \"sequence_id\": \"3\"\n        },\n        \"is_manually_created\": true,\n        \"options\": {},\n        \"created_by\": {\n            \"id\": \"11446498\",\n            \"type\": \"user\",\n            \"name\": \"Aaron Levie\",\n            \"login\": \"ceo@example.com\"\n        },\n        \"modified_by\": {\n            \"id\": \"11446498\",\n            \"type\": \"user\",\n            \"name\": \"Aaron Levie\",\n            \"login\": \"ceo@example.com\"\n        },\n        \"created_at\": \"2012-12-12T10:53:43-08:00\",\n        \"modified_at\": \"2012-12-12T10:53:43-08:00\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/legal_hold_policies_assign_yaml.txt",
    "content": "Type: legal_hold_policy_assignment\nID: '12345'\nLegal Hold Policy:\n    Type: legal_hold_policy\n    ID: '11111'\n    Policy Name: Trial Documents\nAssigned To:\n    Type: folder\n    ID: '55555'\nAssigned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nAssigned At: '2018-04-25T17:07:56-07:00'\nDeleted At: null\nModified At: '2018-04-25T17:07:57-07:00'\n"
  },
  {
    "path": "test/fixtures/output/legal_hold_policies_create_yaml.txt",
    "content": "Type: legal_hold_policy\nID: '11111'\nPolicy Name: Trial Documents\nDescription: ''\nStatus: active\nAssignment Counts:\n    User: 0\n    Folder: 0\n    File: 0\n    File Version: 0\nIs Ongoing: true\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nCreated At: '2018-04-25T16:37:05-07:00'\nModified At: '2018-04-25T16:37:05-07:00'\nDeleted At: null\nFilter Started At: null\nFilter Ended At: null\n"
  },
  {
    "path": "test/fixtures/output/legal_hold_policies_get_assignment_yaml.txt",
    "content": "Type: legal_hold_policy_assignment\nID: '12345'\nLegal Hold Policy:\n    Type: legal_hold_policy\n    ID: '11111'\n    Policy Name: Trial Documents\nAssigned To:\n    Type: folder\n    ID: '55555'\nAssigned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nAssigned At: '2018-04-25T17:07:56-07:00'\nDeleted At: null\nModified At: '2018-04-25T17:07:57-07:00'\n"
  },
  {
    "path": "test/fixtures/output/legal_hold_policies_get_version_hold_yaml.txt",
    "content": "Type: legal_hold\nID: '99999'\nFile Version:\n    Type: file_version\n    ID: '77777'\nFile:\n    Type: file\n    ID: '88888'\n    ETag: '0'\nLegal Hold Policy Assignments:\n    -\n        Type: legal_hold_policy_assignment\n        ID: '12345'\nDeleted At: null\n"
  },
  {
    "path": "test/fixtures/output/legal_hold_policies_get_yaml.txt",
    "content": "Type: legal_hold_policy\nID: '11111'\nPolicy Name: Trial Documents\nDescription: ''\nStatus: active\nAssignment Counts:\n    User: 0\n    Folder: 0\n    File: 0\n    File Version: 0\nIs Ongoing: true\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nCreated At: '2018-04-25T16:37:05-07:00'\nModified At: '2018-04-25T16:37:05-07:00'\nDeleted At: null\nFilter Started At: null\nFilter Ended At: null\n"
  },
  {
    "path": "test/fixtures/output/legal_hold_policies_list_assignments_json.txt",
    "content": "[\n    {\n        \"type\": \"legal_hold_policy_assignment\",\n        \"id\": \"12345\"\n    },\n    {\n        \"type\": \"legal_hold_policy_assignment\",\n        \"id\": \"123456\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/legal_hold_policies_list_json.txt",
    "content": "[\n    {\n        \"type\": \"legal_hold_policy\",\n        \"id\": \"22222\",\n        \"policy_name\": \"IRS Audit\"\n    },\n    {\n        \"type\": \"legal_hold_policy\",\n        \"id\": \"11111\",\n        \"policy_name\": \"Trial Documents\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/legal_hold_policies_list_table.txt",
    "content": "----- Legal Hold Policy 22222 -----\nType: legal_hold_policy\nID: '22222'\nPolicy Name: IRS Audit\n\n----- Legal Hold Policy 11111 -----\nType: legal_hold_policy\nID: '11111'\nPolicy Name: Trial Documents\n"
  },
  {
    "path": "test/fixtures/output/legal_hold_policies_list_version_holds_json.txt",
    "content": "[\n    {\n        \"type\": \"legal_hold\",\n        \"id\": \"99999\"\n    },\n    {\n        \"type\": \"legal_hold\",\n        \"id\": \"99990\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/legal_hold_policies_list_yaml.txt",
    "content": "Entries:\n    -\n        Type: legal_hold_policy\n        ID: '22222'\n        Policy Name: IRS Audit\n    -\n        Type: legal_hold_policy\n        ID: '11111'\n        Policy Name: Trial Documents\nLimit: 100\nOrder:\n    -\n        By: policy_name\n        Direction: ASC\n"
  },
  {
    "path": "test/fixtures/output/legal_hold_policies_update_yaml.txt",
    "content": "Type: legal_hold_policy\nID: '11111'\nPolicy Name: Trial Documents\nDescription: Documents related to our ongoing litigation\nStatus: active\nAssignment Counts:\n    User: 0\n    Folder: 0\n    File: 0\n    File Version: 0\nIs Ongoing: true\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nCreated At: '2018-04-25T16:37:05-07:00'\nModified At: '2018-04-25T16:45:55-07:00'\nDeleted At: null\nFilter Started At: null\nFilter Ended At: null\n"
  },
  {
    "path": "test/fixtures/output/metadata_cascade_policies_create_yaml.txt",
    "content": "ID: 84113349-794d-445c-b93c-d8481b223434\nType: metadata_cascade_policy\nOwner Enterprise:\n    Type: enterprise\n    ID: '11111'\nParent:\n    Type: folder\n    ID: '22222'\nScope: enterprise_11111\nTemplate Key: testTemplate\n"
  },
  {
    "path": "test/fixtures/output/metadata_cascade_policies_get_yaml.txt",
    "content": "ID: 84113349-794d-445c-b93c-d8481b223434\nType: metadata_cascade_policy\nOwner Enterprise:\n    Type: enterprise\n    ID: '11111'\nParent:\n    Type: folder\n    ID: '22222'\nScope: enterprise_11111\nTemplate Key: testTemplate\n"
  },
  {
    "path": "test/fixtures/output/metadata_cascade_policies_list_json.txt",
    "content": "[\n    {\n        \"id\": \"84113349-794d-445c-b93c-d8481b223434\",\n        \"type\": \"metadata_cascade_policy\",\n        \"owner_enterprise\": {\n            \"type\": \"enterprise\",\n            \"id\": \"11111\"\n        },\n        \"parent\": {\n            \"type\": \"folder\",\n            \"id\": \"22222\"\n        },\n        \"scope\": \"enterprise_11111\",\n        \"templateKey\": \"testTemplate\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/metadata_cascade_policies_list_table.txt",
    "content": "----- Metadata Cascade Policy 84113349-794d-445c-b93c-d8481b223434 -----\nID: 84113349-794d-445c-b93c-d8481b223434\nType: metadata_cascade_policy\nOwner Enterprise:\n    Type: enterprise\n    ID: '11111'\nParent:\n    Type: folder\n    ID: '22222'\nScope: enterprise_11111\nTemplate Key: testTemplate\n"
  },
  {
    "path": "test/fixtures/output/metadata_templates_create_yaml.txt",
    "content": "ID: 687735ca-1325-4e50-8f30-6d4683997fa4\nType: metadata_template\nTemplate Key: newMetadata\nScope: enterprise_12345\nDisplay Name: New Metadata Template\nHidden: true\nCopy Instance On Item Copy: true\nFields:\n    -\n        ID: 3c7ba014-e136-49e3-a0aa-f48588ddd223\n        Type: string\n        Key: name\n        Display Name: Name\n        Hidden: false\n    -\n        ID: eb30bfc1-a165-4439-bec3-53e349ee7671\n        Type: enum\n        Key: location\n        Display Name: Location\n        Hidden: false\n        Options:\n            -\n                ID: b8435f07-e332-4493-9add-18aeaed73551\n                Key: US\n            -\n                ID: 4cdb3b26-5bba-4433-b8b8-22b89f372735\n                Key: EU\n    -\n        ID: 6e311d0e-7133-4b72-a3aa-199c723796e3\n        Type: date\n        Key: date\n        Display Name: Date\n        Hidden: false\n"
  },
  {
    "path": "test/fixtures/output/metadata_templates_get_yaml.txt",
    "content": "ID: 1ba96432-c223-4797-95a9-1636b59c3f7b\nType: metadata_template\nTemplate Key: testTemplate\nScope: enterprise_12345\nDisplay Name: Test Template\nHidden: false\nFields:\n    -\n        ID: 1f2f29a6-00e2-4b56-b246-b50d5494b2ca\n        Type: enum\n        Key: testEnum\n        Display Name: Test Enum\n        Hidden: false\n        Options:\n            -\n                ID: c84b76d2-db68-4fc2-9a75-4b7820845fa8\n                Key: foo\n            -\n                ID: 6ee108f2-41f0-43e2-1584-06316c37badf\n                Key: bar\n"
  },
  {
    "path": "test/fixtures/output/metadata_templates_list_json.txt",
    "content": "[\n    {\n        \"id\": \"71274d65-cf63-40dc-b119-d4da31071492\",\n        \"type\": \"metadata_template\",\n        \"templateKey\": \"mymetadata\",\n        \"scope\": \"enterprise_12345\",\n        \"displayName\": \"MyMetadata\",\n        \"hidden\": false,\n        \"fields\": [\n            {\n                \"id\": \"6ff16602-0119-4619-ae15-f02b1ecdd811\",\n                \"type\": \"string\",\n                \"key\": \"data\",\n                \"displayName\": \"Data\",\n                \"hidden\": false\n            },\n            {\n                \"id\": \"5c16d86c-6554-4278-814e-356211215807\",\n                \"type\": \"date\",\n                \"key\": \"when\",\n                \"displayName\": \"When\",\n                \"hidden\": false\n            }\n        ]\n    },\n    {\n        \"id\": \"1ba164d2-c223-4797-92a9-1616b29c3f72\",\n        \"type\": \"metadata_template\",\n        \"templateKey\": \"testTemplate\",\n        \"scope\": \"enterprise_12345\",\n        \"displayName\": \"Test Template\",\n        \"hidden\": false,\n        \"fields\": [\n            {\n                \"id\": \"1f1f29a6-00e2-4b56-b446-b50d5491b0ca\",\n                \"type\": \"enum\",\n                \"key\": \"testEnum\",\n                \"displayName\": \"Test Enum\",\n                \"hidden\": false,\n                \"options\": [\n                    {\n                        \"id\": \"c84b16d2-db68-4fc2-9a85-4b8820841fa8\",\n                        \"key\": \"foo\"\n                    },\n                    {\n                        \"id\": \"6ee108f2-47f0-43e2-9584-06311c37badf\",\n                        \"key\": \"bar\"\n                    }\n                ]\n            }\n        ]\n    },\n    {\n        \"id\": \"81274d65-cf63-40dc-b119-d4da31071492\",\n        \"type\": \"metadata_template\",\n        \"templateKey\": \"mymetadata\",\n        \"scope\": \"enterprise_12345\",\n        \"displayName\": \"MyMetadata\",\n        \"hidden\": false,\n        \"fields\": [\n            {\n                \"id\": \"6ff16602-0119-4619-ae15-f02b1ecdd811\",\n                \"type\": \"string\",\n                \"key\": \"data\",\n                \"displayName\": \"Data\",\n                \"hidden\": false\n            },\n            {\n                \"id\": \"5c16d86c-6554-4278-814e-356211215807\",\n                \"type\": \"date\",\n                \"key\": \"when\",\n                \"displayName\": \"When\",\n                \"hidden\": false\n            }\n        ]\n    },\n    {\n        \"id\": \"8ba164d2-c223-4797-92a9-1616b29c3f72\",\n        \"type\": \"metadata_template\",\n        \"templateKey\": \"testTemplate\",\n        \"scope\": \"enterprise_12345\",\n        \"displayName\": \"Test Template\",\n        \"hidden\": false,\n        \"fields\": [\n            {\n                \"id\": \"1f1f29a6-00e2-4b56-b446-b50d5491b0ca\",\n                \"type\": \"enum\",\n                \"key\": \"testEnum\",\n                \"displayName\": \"Test Enum\",\n                \"hidden\": false,\n                \"options\": [\n                    {\n                        \"id\": \"c84b16d2-db68-4fc2-9a85-4b8820841fa8\",\n                        \"key\": \"foo\"\n                    },\n                    {\n                        \"id\": \"6ee108f2-47f0-43e2-9584-06311c37badf\",\n                        \"key\": \"bar\"\n                    }\n                ]\n            }\n        ]\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/recent_items_json.txt",
    "content": "[\n    {\n        \"type\": \"recent_item\",\n        \"interaction_type\": \"item_preview\",\n        \"interacted_at\": \"2018-04-25T17:07:44-07:00\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"11111\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"111110\",\n                \"sha1\": \"3c0b046ef81f262cb5b2e417b45c7aaa507a5628\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"3c0b046ef81f262cb5b2e417b45c7aaa507a5628\",\n            \"name\": \"Instruction Manual.pdf\"\n        },\n        \"interaction_shared_link\": null\n    },\n    {\n        \"type\": \"recent_item\",\n        \"interaction_type\": \"item_preview\",\n        \"interacted_at\": \"2018-04-24T17:22:11-07:00\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"22222\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"222220\",\n                \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n            },\n            \"sequence_id\": \"9\",\n            \"etag\": \"9\",\n            \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n            \"name\": \"test file.txt\"\n        },\n        \"interaction_shared_link\": null\n    },\n    {\n        \"type\": \"recent_item\",\n        \"interaction_type\": \"item_preview\",\n        \"interacted_at\": \"2018-04-24T16:49:13-07:00\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"44444\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"444440\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"Copied file.txt\"\n        },\n        \"interaction_shared_link\": null\n    },\n    {\n        \"type\": \"recent_item\",\n        \"interaction_type\": \"item_preview\",\n        \"interacted_at\": \"2018-04-25T17:07:44-07:00\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"11112\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"111110\",\n                \"sha1\": \"3c0b046ef81f262cb5b2e417b45c7aaa507a5628\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"3c0b046ef81f262cb5b2e417b45c7aaa507a5628\",\n            \"name\": \"Instruction Manual.pdf\"\n        },\n        \"interaction_shared_link\": null\n    },\n    {\n        \"type\": \"recent_item\",\n        \"interaction_type\": \"item_preview\",\n        \"interacted_at\": \"2018-04-24T17:22:11-07:00\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"22223\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"222220\",\n                \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n            },\n            \"sequence_id\": \"9\",\n            \"etag\": \"9\",\n            \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n            \"name\": \"test file.txt\"\n        },\n        \"interaction_shared_link\": null\n    },\n    {\n        \"type\": \"recent_item\",\n        \"interaction_type\": \"item_preview\",\n        \"interacted_at\": \"2018-04-24T16:49:13-07:00\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"44445\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"444440\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"Copied file.txt\"\n        },\n        \"interaction_shared_link\": null\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/retention_policies_assign_yaml.txt",
    "content": "Type: retention_policy_assignment\nID: '12345'\nRetention Policy:\n    Type: retention_policy\n    ID: '11111'\n    Policy Name: Retained Financial Records\nAssigned To:\n    Type: folder\n    ID: '22222'\nFilter Fields: []\nAssigned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nAssigned At: '2018-04-25T20:19:16-07:00'\n"
  },
  {
    "path": "test/fixtures/output/retention_policies_create_yaml.txt",
    "content": "Type: retention_policy\nID: '11111'\nPolicy Name: Financial Records\nPolicy Type: finite\nRetention Length: '365'\nRetention Type: modifiable\nDisposition Action: remove_retention\nCan Owner Extend Retention: false\nStatus: active\nAre Owners Notified: false\nCustom Notification Recipients: []\nAssignment Counts:\n    Enterprise: 0\n    Folder: 0\n    Metadata Template: 0\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nCreated At: '2018-04-25T18:29:40-07:00'\nModified At: '2018-04-25T18:29:40-07:00'\n"
  },
  {
    "path": "test/fixtures/output/retention_policies_get_assignment_yaml.txt",
    "content": "Type: retention_policy_assignment\nID: '12345'\nRetention Policy:\n    Type: retention_policy\n    ID: '11111'\n    Policy Name: Retained Financial Records\nAssigned To:\n    Type: folder\n    ID: '22222'\nFilter Fields: []\nAssigned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nAssigned At: '2018-04-25T20:19:16-07:00'\n"
  },
  {
    "path": "test/fixtures/output/retention_policies_get_file_versions_under_retention_json.txt",
    "content": "[\n    {\n        \"id\": 12345,\n        \"etag\": 1,\n        \"type\": \"file_version\",\n        \"sequence_id\": 3,\n        \"name\": \"Contract.pdf\",\n        \"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\",\n        \"file_version\": {\n            \"id\": 12345,\n            \"type\": \"file_version\",\n            \"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n        },\n        \"applied_at\": \"2012-12-12T10:53:43-08:00\"\n    },\n    {\n        \"id\": 67890,\n        \"etag\": 1,\n        \"type\": \"file_version\",\n        \"sequence_id\": 3,\n        \"name\": \"Document.pdf\",\n        \"sha1\": \"018EE5D1D1E0D0727CED62CA5F1B71F6F07AB96B\",\n        \"file_version\": {\n            \"id\": 67890,\n            \"type\": \"file_version\",\n            \"sha1\": \"18CA54DC8372620C1E46ADE6D56FF220A19D01F8\"\n        },\n        \"applied_at\": \"2012-12-12T10:53:43-08:00\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/retention_policies_get_files_under_retention_json.txt",
    "content": "[\n    {\n        \"id\": 12345,\n        \"etag\": 1,\n        \"type\": \"file\",\n        \"sequence_id\": 3,\n        \"name\": \"Contract.pdf\",\n        \"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\",\n        \"file_version\": {\n            \"id\": 123456,\n            \"type\": \"file_version\",\n            \"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n        },\n        \"applied_at\": \"2012-12-12T10:53:43-08:00\"\n    },\n    {\n        \"id\": 6789,\n        \"etag\": 1,\n        \"type\": \"file\",\n        \"sequence_id\": 3,\n        \"name\": \"Document.pdf\",\n        \"sha1\": \"3C363836CF4E16666669A25DA280A1865C2D2874\",\n        \"file_version\": {\n            \"id\": 67890,\n            \"type\": \"file_version\",\n            \"sha1\": \"2813c90c8178bf651a75ca1b96f015ce3def166b\"\n        },\n        \"applied_at\": \"2012-12-12T10:53:43-08:00\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/retention_policies_get_version_retention_yaml.txt",
    "content": "Type: file_version_retention\nID: '444444'\nApplied At: '2016-12-08T11:22:18-08:00'\nDisposition At: '2106-02-06T22:28:15-08:00'\nWinning Retention Policy:\n    Type: retention_policy\n    ID: '22222'\n    Policy Name: Retain Times Infinity\nFile Version:\n    Type: file_version\n    ID: '111110'\n    SHA1: null\nFile:\n    Type: file\n    ID: '11111'\n    ETag: '0'\n"
  },
  {
    "path": "test/fixtures/output/retention_policies_get_yaml.txt",
    "content": "Type: retention_policy\nID: '11111'\nPolicy Name: Financial Records\nPolicy Type: finite\nRetention Length: '365'\nDisposition Action: remove_retention\nCan Owner Extend Retention: false\nStatus: active\nAre Owners Notified: false\nCustom Notification Recipients: []\nAssignment Counts:\n    Enterprise: 0\n    Folder: 0\n    Metadata Template: 0\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nCreated At: '2018-04-25T18:29:40-07:00'\nModified At: '2018-04-25T18:29:40-07:00'\n"
  },
  {
    "path": "test/fixtures/output/retention_policies_list_assignments_json.txt",
    "content": "[\n    {\n        \"type\": \"retention_policy_assignment\",\n        \"id\": \"12345\"\n    },\n    {\n        \"type\": \"retention_policy_assignment\",\n        \"id\": \"123456\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/retention_policies_list_json.txt",
    "content": "[\n    {\n        \"type\": \"retention_policy\",\n        \"id\": \"44444\",\n        \"policy_name\": \"My Policy\"\n    },\n    {\n        \"type\": \"retention_policy\",\n        \"id\": \"33333\",\n        \"policy_name\": \"Retain Forever\"\n    },\n    {\n        \"type\": \"retention_policy\",\n        \"id\": \"11111\",\n        \"policy_name\": \"Retained Financial Records\"\n    },\n    {\n        \"type\": \"retention_policy\",\n        \"id\": \"22222\",\n        \"policy_name\": \"Very Short Retention\"\n    },\n    {\n        \"type\": \"retention_policy\",\n        \"id\": \"44445\",\n        \"policy_name\": \"My Policy\"\n    },\n    {\n        \"type\": \"retention_policy\",\n        \"id\": \"33334\",\n        \"policy_name\": \"Retain Forever\"\n    },\n    {\n        \"type\": \"retention_policy\",\n        \"id\": \"11112\",\n        \"policy_name\": \"Retained Financial Records\"\n    },\n    {\n        \"type\": \"retention_policy\",\n        \"id\": \"22223\",\n        \"policy_name\": \"Very Short Retention\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/retention_policies_list_version_retentions_json.txt",
    "content": "[\n    {\n        \"type\": \"file_version_retention\",\n        \"id\": \"111111\"\n    },\n    {\n        \"type\": \"file_version_retention\",\n        \"id\": \"222222\"\n    },\n    {\n        \"type\": \"file_version_retention\",\n        \"id\": \"333333\"\n    },\n    {\n        \"type\": \"file_version_retention\",\n        \"id\": \"444444\"\n    },\n    {\n        \"type\": \"file_version_retention\",\n        \"id\": \"111112\"\n    },\n    {\n        \"type\": \"file_version_retention\",\n        \"id\": \"222223\"\n    },\n    {\n        \"type\": \"file_version_retention\",\n        \"id\": \"333334\"\n    },\n    {\n        \"type\": \"file_version_retention\",\n        \"id\": \"444445\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/retention_policies_update_yaml.txt",
    "content": "Type: retention_policy\nID: '11111'\nPolicy Name: Retained Financial Records\nPolicy Type: finite\nRetention Length: '365'\nRetention Type: non_modifiable\nDisposition Action: remove_retention\nCan Owner Extend Retention: false\nStatus: active\nAre Owners Notified: false\nCustom Notification Recipients: []\nAssignment Counts:\n    Enterprise: 0\n    Folder: 0\n    Metadata Template: 0\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nCreated At: '2018-04-25T18:29:40-07:00'\nModified At: '2018-04-25T18:29:40-07:00'\n"
  },
  {
    "path": "test/fixtures/output/search_json.txt",
    "content": "[\n    {\n        \"type\": \"file\",\n        \"id\": \"11111\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"111110\",\n            \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n        },\n        \"sequence_id\": \"9\",\n        \"etag\": \"9\",\n        \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n        \"name\": \"test file.txt\",\n        \"description\": \"\",\n        \"size\": 16,\n        \"path_collection\": {\n            \"total_count\": 1,\n            \"entries\": [\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"0\",\n                    \"sequence_id\": null,\n                    \"etag\": null,\n                    \"name\": \"All Files\"\n                }\n            ]\n        },\n        \"created_at\": \"2016-12-07T15:53:59-08:00\",\n        \"modified_at\": \"2018-04-24T15:08:58-07:00\",\n        \"trashed_at\": null,\n        \"purged_at\": null,\n        \"content_created_at\": \"2016-12-07T15:53:59-08:00\",\n        \"content_modified_at\": \"2016-12-07T15:59:32-08:00\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"shared_link\": null,\n        \"parent\": {\n            \"type\": \"folder\",\n            \"id\": \"0\",\n            \"sequence_id\": null,\n            \"etag\": null,\n            \"name\": \"All Files\"\n        },\n        \"item_status\": \"active\"\n    },\n    {\n        \"type\": \"folder\",\n        \"id\": \"22222\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"name\": \"Test Folder\",\n        \"created_at\": \"2016-12-07T16:34:50-08:00\",\n        \"modified_at\": \"2016-12-07T16:34:50-08:00\",\n        \"description\": \"\",\n        \"size\": 0,\n        \"path_collection\": {\n            \"total_count\": 1,\n            \"entries\": [\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"0\",\n                    \"sequence_id\": null,\n                    \"etag\": null,\n                    \"name\": \"All Files\"\n                }\n            ]\n        },\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"trashed_at\": null,\n        \"purged_at\": null,\n        \"content_created_at\": \"2016-12-07T16:34:50-08:00\",\n        \"content_modified_at\": \"2016-12-07T16:34:50-08:00\",\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"shared_link\": null,\n        \"folder_upload_email\": null,\n        \"parent\": null,\n        \"item_status\": \"active\"\n    },\n    {\n        \"type\": \"folder\",\n        \"id\": \"33333\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"SDK Test Folder\",\n        \"created_at\": \"2016-12-07T15:23:44-08:00\",\n        \"modified_at\": \"2016-12-07T15:23:44-08:00\",\n        \"description\": \"\",\n        \"size\": 0,\n        \"path_collection\": {\n            \"total_count\": 1,\n            \"entries\": [\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"0\",\n                    \"sequence_id\": null,\n                    \"etag\": null,\n                    \"name\": \"All Files\"\n                }\n            ]\n        },\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"trashed_at\": null,\n        \"purged_at\": null,\n        \"content_created_at\": \"2016-12-07T15:23:44-08:00\",\n        \"content_modified_at\": \"2016-12-07T15:23:44-08:00\",\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"shared_link\": null,\n        \"folder_upload_email\": null,\n        \"parent\": {\n            \"type\": \"folder\",\n            \"id\": \"0\",\n            \"sequence_id\": null,\n            \"etag\": null,\n            \"name\": \"All Files\"\n        },\n        \"item_status\": \"active\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"44444\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"444440\",\n            \"sha1\": \"12717919be7d81be2a30824d9cf1d0f9aa4465ab\"\n        },\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"sha1\": \"12717919be7d81be2a30824d9cf1d0f9aa4465ab\",\n        \"name\": \"test.js\",\n        \"description\": \"\",\n        \"size\": 362,\n        \"path_collection\": {\n            \"total_count\": 2,\n            \"entries\": [\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"0\",\n                    \"sequence_id\": null,\n                    \"etag\": null,\n                    \"name\": \"All Files\"\n                },\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"12345\",\n                    \"sequence_id\": \"0\",\n                    \"etag\": \"0\",\n                    \"name\": \"Copied Folder\"\n                }\n            ]\n        },\n        \"created_at\": \"2016-12-08T11:50:43-08:00\",\n        \"modified_at\": \"2016-12-08T14:48:18-08:00\",\n        \"trashed_at\": null,\n        \"purged_at\": null,\n        \"content_created_at\": \"2015-12-17T23:10:11-08:00\",\n        \"content_modified_at\": \"2015-12-17T23:10:11-08:00\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"shared_link\": null,\n        \"parent\": {\n            \"type\": \"folder\",\n            \"id\": \"12345\",\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"name\": \"Copied Folder\"\n        },\n        \"item_status\": \"active\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"55555\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"555550\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n        },\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n        \"name\": \"Copied file.txt\",\n        \"description\": \"\",\n        \"size\": 9,\n        \"path_collection\": {\n            \"total_count\": 1,\n            \"entries\": [\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"0\",\n                    \"sequence_id\": null,\n                    \"etag\": null,\n                    \"name\": \"All Files\"\n                }\n            ]\n        },\n        \"created_at\": \"2016-12-07T15:56:54-08:00\",\n        \"modified_at\": \"2016-12-07T15:56:54-08:00\",\n        \"trashed_at\": null,\n        \"purged_at\": null,\n        \"content_created_at\": \"2016-12-07T15:53:59-08:00\",\n        \"content_modified_at\": \"2016-12-07T15:53:59-08:00\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"shared_link\": null,\n        \"parent\": {\n            \"type\": \"folder\",\n            \"id\": \"0\",\n            \"sequence_id\": null,\n            \"etag\": null,\n            \"name\": \"All Files\"\n        },\n        \"item_status\": \"active\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"111112\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"111110\",\n            \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n        },\n        \"sequence_id\": \"9\",\n        \"etag\": \"9\",\n        \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n        \"name\": \"test file.txt\",\n        \"description\": \"\",\n        \"size\": 16,\n        \"path_collection\": {\n            \"total_count\": 1,\n            \"entries\": [\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"0\",\n                    \"sequence_id\": null,\n                    \"etag\": null,\n                    \"name\": \"All Files\"\n                }\n            ]\n        },\n        \"created_at\": \"2016-12-07T15:53:59-08:00\",\n        \"modified_at\": \"2018-04-24T15:08:58-07:00\",\n        \"trashed_at\": null,\n        \"purged_at\": null,\n        \"content_created_at\": \"2016-12-07T15:53:59-08:00\",\n        \"content_modified_at\": \"2016-12-07T15:59:32-08:00\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"shared_link\": null,\n        \"parent\": {\n            \"type\": \"folder\",\n            \"id\": \"0\",\n            \"sequence_id\": null,\n            \"etag\": null,\n            \"name\": \"All Files\"\n        },\n        \"item_status\": \"active\"\n    },\n    {\n        \"type\": \"folder\",\n        \"id\": \"222223\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"name\": \"Test Folder\",\n        \"created_at\": \"2016-12-07T16:34:50-08:00\",\n        \"modified_at\": \"2016-12-07T16:34:50-08:00\",\n        \"description\": \"\",\n        \"size\": 0,\n        \"path_collection\": {\n            \"total_count\": 1,\n            \"entries\": [\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"0\",\n                    \"sequence_id\": null,\n                    \"etag\": null,\n                    \"name\": \"All Files\"\n                }\n            ]\n        },\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"trashed_at\": null,\n        \"purged_at\": null,\n        \"content_created_at\": \"2016-12-07T16:34:50-08:00\",\n        \"content_modified_at\": \"2016-12-07T16:34:50-08:00\",\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"shared_link\": null,\n        \"folder_upload_email\": null,\n        \"parent\": null,\n        \"item_status\": \"active\"\n    },\n    {\n        \"type\": \"folder\",\n        \"id\": \"333334\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"SDK Test Folder\",\n        \"created_at\": \"2016-12-07T15:23:44-08:00\",\n        \"modified_at\": \"2016-12-07T15:23:44-08:00\",\n        \"description\": \"\",\n        \"size\": 0,\n        \"path_collection\": {\n            \"total_count\": 1,\n            \"entries\": [\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"0\",\n                    \"sequence_id\": null,\n                    \"etag\": null,\n                    \"name\": \"All Files\"\n                }\n            ]\n        },\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"trashed_at\": null,\n        \"purged_at\": null,\n        \"content_created_at\": \"2016-12-07T15:23:44-08:00\",\n        \"content_modified_at\": \"2016-12-07T15:23:44-08:00\",\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"shared_link\": null,\n        \"folder_upload_email\": null,\n        \"parent\": {\n            \"type\": \"folder\",\n            \"id\": \"0\",\n            \"sequence_id\": null,\n            \"etag\": null,\n            \"name\": \"All Files\"\n        },\n        \"item_status\": \"active\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"444445\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"444440\",\n            \"sha1\": \"12717919be7d81be2a30824d9cf1d0f9aa4465ab\"\n        },\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"sha1\": \"12717919be7d81be2a30824d9cf1d0f9aa4465ab\",\n        \"name\": \"test.js\",\n        \"description\": \"\",\n        \"size\": 362,\n        \"path_collection\": {\n            \"total_count\": 2,\n            \"entries\": [\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"0\",\n                    \"sequence_id\": null,\n                    \"etag\": null,\n                    \"name\": \"All Files\"\n                },\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"12345\",\n                    \"sequence_id\": \"0\",\n                    \"etag\": \"0\",\n                    \"name\": \"Copied Folder\"\n                }\n            ]\n        },\n        \"created_at\": \"2016-12-08T11:50:43-08:00\",\n        \"modified_at\": \"2016-12-08T14:48:18-08:00\",\n        \"trashed_at\": null,\n        \"purged_at\": null,\n        \"content_created_at\": \"2015-12-17T23:10:11-08:00\",\n        \"content_modified_at\": \"2015-12-17T23:10:11-08:00\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"shared_link\": null,\n        \"parent\": {\n            \"type\": \"folder\",\n            \"id\": \"12345\",\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"name\": \"Copied Folder\"\n        },\n        \"item_status\": \"active\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"555556\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"555550\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n        },\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n        \"name\": \"Copied file.txt\",\n        \"description\": \"\",\n        \"size\": 9,\n        \"path_collection\": {\n            \"total_count\": 1,\n            \"entries\": [\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"0\",\n                    \"sequence_id\": null,\n                    \"etag\": null,\n                    \"name\": \"All Files\"\n                }\n            ]\n        },\n        \"created_at\": \"2016-12-07T15:56:54-08:00\",\n        \"modified_at\": \"2016-12-07T15:56:54-08:00\",\n        \"trashed_at\": null,\n        \"purged_at\": null,\n        \"content_created_at\": \"2016-12-07T15:53:59-08:00\",\n        \"content_modified_at\": \"2016-12-07T15:53:59-08:00\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"shared_link\": null,\n        \"parent\": {\n            \"type\": \"folder\",\n            \"id\": \"0\",\n            \"sequence_id\": null,\n            \"etag\": null,\n            \"name\": \"All Files\"\n        },\n        \"item_status\": \"active\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/search_json_limit_5.txt",
    "content": "[\n    {\n        \"type\": \"file\",\n        \"id\": \"11111\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"111110\",\n            \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n        },\n        \"sequence_id\": \"9\",\n        \"etag\": \"9\",\n        \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n        \"name\": \"test file.txt\",\n        \"description\": \"\",\n        \"size\": 16,\n        \"path_collection\": {\n            \"total_count\": 1,\n            \"entries\": [\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"0\",\n                    \"sequence_id\": null,\n                    \"etag\": null,\n                    \"name\": \"All Files\"\n                }\n            ]\n        },\n        \"created_at\": \"2016-12-07T15:53:59-08:00\",\n        \"modified_at\": \"2018-04-24T15:08:58-07:00\",\n        \"trashed_at\": null,\n        \"purged_at\": null,\n        \"content_created_at\": \"2016-12-07T15:53:59-08:00\",\n        \"content_modified_at\": \"2016-12-07T15:59:32-08:00\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"shared_link\": null,\n        \"parent\": {\n            \"type\": \"folder\",\n            \"id\": \"0\",\n            \"sequence_id\": null,\n            \"etag\": null,\n            \"name\": \"All Files\"\n        },\n        \"item_status\": \"active\"\n    },\n    {\n        \"type\": \"folder\",\n        \"id\": \"22222\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"name\": \"Test Folder\",\n        \"created_at\": \"2016-12-07T16:34:50-08:00\",\n        \"modified_at\": \"2016-12-07T16:34:50-08:00\",\n        \"description\": \"\",\n        \"size\": 0,\n        \"path_collection\": {\n            \"total_count\": 1,\n            \"entries\": [\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"0\",\n                    \"sequence_id\": null,\n                    \"etag\": null,\n                    \"name\": \"All Files\"\n                }\n            ]\n        },\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"trashed_at\": null,\n        \"purged_at\": null,\n        \"content_created_at\": \"2016-12-07T16:34:50-08:00\",\n        \"content_modified_at\": \"2016-12-07T16:34:50-08:00\",\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"shared_link\": null,\n        \"folder_upload_email\": null,\n        \"parent\": null,\n        \"item_status\": \"active\"\n    },\n    {\n        \"type\": \"folder\",\n        \"id\": \"33333\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"SDK Test Folder\",\n        \"created_at\": \"2016-12-07T15:23:44-08:00\",\n        \"modified_at\": \"2016-12-07T15:23:44-08:00\",\n        \"description\": \"\",\n        \"size\": 0,\n        \"path_collection\": {\n            \"total_count\": 1,\n            \"entries\": [\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"0\",\n                    \"sequence_id\": null,\n                    \"etag\": null,\n                    \"name\": \"All Files\"\n                }\n            ]\n        },\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"trashed_at\": null,\n        \"purged_at\": null,\n        \"content_created_at\": \"2016-12-07T15:23:44-08:00\",\n        \"content_modified_at\": \"2016-12-07T15:23:44-08:00\",\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"shared_link\": null,\n        \"folder_upload_email\": null,\n        \"parent\": {\n            \"type\": \"folder\",\n            \"id\": \"0\",\n            \"sequence_id\": null,\n            \"etag\": null,\n            \"name\": \"All Files\"\n        },\n        \"item_status\": \"active\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"44444\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"444440\",\n            \"sha1\": \"12717919be7d81be2a30824d9cf1d0f9aa4465ab\"\n        },\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"sha1\": \"12717919be7d81be2a30824d9cf1d0f9aa4465ab\",\n        \"name\": \"test.js\",\n        \"description\": \"\",\n        \"size\": 362,\n        \"path_collection\": {\n            \"total_count\": 2,\n            \"entries\": [\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"0\",\n                    \"sequence_id\": null,\n                    \"etag\": null,\n                    \"name\": \"All Files\"\n                },\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"12345\",\n                    \"sequence_id\": \"0\",\n                    \"etag\": \"0\",\n                    \"name\": \"Copied Folder\"\n                }\n            ]\n        },\n        \"created_at\": \"2016-12-08T11:50:43-08:00\",\n        \"modified_at\": \"2016-12-08T14:48:18-08:00\",\n        \"trashed_at\": null,\n        \"purged_at\": null,\n        \"content_created_at\": \"2015-12-17T23:10:11-08:00\",\n        \"content_modified_at\": \"2015-12-17T23:10:11-08:00\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"shared_link\": null,\n        \"parent\": {\n            \"type\": \"folder\",\n            \"id\": \"12345\",\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"name\": \"Copied Folder\"\n        },\n        \"item_status\": \"active\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"55555\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"555550\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n        },\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n        \"name\": \"Copied file.txt\",\n        \"description\": \"\",\n        \"size\": 9,\n        \"path_collection\": {\n            \"total_count\": 1,\n            \"entries\": [\n                {\n                    \"type\": \"folder\",\n                    \"id\": \"0\",\n                    \"sequence_id\": null,\n                    \"etag\": null,\n                    \"name\": \"All Files\"\n                }\n            ]\n        },\n        \"created_at\": \"2016-12-07T15:56:54-08:00\",\n        \"modified_at\": \"2016-12-07T15:56:54-08:00\",\n        \"trashed_at\": null,\n        \"purged_at\": null,\n        \"content_created_at\": \"2016-12-07T15:53:59-08:00\",\n        \"content_modified_at\": \"2016-12-07T15:53:59-08:00\",\n        \"created_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"modified_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"owned_by\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        },\n        \"shared_link\": null,\n        \"parent\": {\n            \"type\": \"folder\",\n            \"id\": \"0\",\n            \"sequence_id\": null,\n            \"etag\": null,\n            \"name\": \"All Files\"\n        },\n        \"item_status\": \"active\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/shared_links_get_yaml.txt",
    "content": "Type: file\nID: '11111'\nFile Version:\n    Type: file_version\n    ID: '111110'\n    SHA1: de37fa51bfc28ad1cbbd5ca4edb895e57651b2fc\nSequence ID: '1'\nETag: '1'\nSHA1: de37fa51bfc28ad1cbbd5ca4edb895e57651b2fc\nName: Spreadsheet.csv\nDescription: ''\nSize: 343\nPath Collection:\n    Total Count: 0\n    Entries: []\nCreated At: '2016-09-19T11:16:59-07:00'\nModified At: '2016-09-19T11:16:59-07:00'\nTrashed At: null\nPurged At: null\nContent Created At: '2016-09-19T11:16:59-07:00'\nContent Modified At: '2016-09-19T11:16:59-07:00'\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nModified By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nOwned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nShared Link: null\nParent: null\nItem Status: active\n"
  },
  {
    "path": "test/fixtures/output/sign_templates_json.txt",
    "content": "[\n    {\n        \"id\": \"93153068-5420-467b-b8ef-aaaaaaaaaaa\",\n        \"name\": \"contract.pdf\",\n        \"email_message\": \"Please sign this document.\\n\\nKind regards,\\n\\nSomeone\",\n        \"email_subject\": \"Someone has requested your signature on a document\",\n        \"parent_folder\": {\n            \"id\": \"1234567890\",\n            \"etag\": \"0\",\n            \"type\": \"folder\",\n            \"sequence_id\": \"0\",\n            \"name\": \"My Sign Requests\"\n        },\n        \"auto_expire_days\": null,\n        \"source_files\": [\n            {\n                \"id\": \"1234567890\",\n                \"etag\": \"0\",\n                \"type\": \"file\",\n                \"sequence_id\": \"0\",\n                \"sha1\": \"082c9540e82e9c465309367a32404054b13aaaaaa\",\n                \"file_version\": {\n                    \"id\": \"1234567890\",\n                    \"type\": \"file_version\",\n                    \"sha1\": \"082c9540e82e9c465309367a32404054b13aaaaaa\"\n                }\n            }\n        ],\n        \"are_email_settings_locked\": false,\n        \"are_fields_locked\": false,\n        \"are_files_locked\": false,\n        \"are_options_locked\": false,\n        \"are_recipients_locked\": false,\n        \"signers\": [\n            {\n                \"email\": \"\",\n                \"label\": \"\",\n                \"public_id\": \"18K8KAAA\",\n                \"role\": \"final_copy_reader\",\n                \"is_in_person\": false,\n                \"order\": 1,\n                \"inputs\": []\n            },\n            {\n                \"email\": \"\",\n                \"label\": \"\",\n                \"public_id\": \"13XQXAAA\",\n                \"role\": \"signer\",\n                \"is_in_person\": false,\n                \"order\": 1,\n                \"inputs\": [\n                    {\n                        \"document_tag_id\": null,\n                        \"id\": \"0260f921-3b52-477f-ae74-aaaaaaaaaaa\",\n                        \"type\": \"signature\",\n                        \"text_value\": null,\n                        \"is_required\": true,\n                        \"coordinates\": {\n                            \"x\": 0.27038464059712,\n                            \"y\": 0.10051756244533624\n                        },\n                        \"dimensions\": {\n                            \"width\": 0.23570031566618235,\n                            \"height\": 0.04781003891921971\n                        },\n                        \"date_value\": null,\n                        \"page_index\": 0,\n                        \"checkbox_value\": null,\n                        \"document_id\": \"2fdf9003-d798-40ee-be7f-aaaaaaaaaaa\",\n                        \"content_type\": \"signature\",\n                        \"dropdown_choices\": null,\n                        \"group_id\": null,\n                        \"label\": null\n                    }\n                ]\n            }\n        ],\n        \"ready_sign_link\": {\n            \"url\": \"https://app.box.com/sign/ready-sign-link/59917816-c12b-4ef6-8f1d-aaaaaaaaaaa\",\n            \"name\": \"contract.pdf\",\n            \"instructions\": \"Hello\",\n            \"folder_id\": \"1234567890\",\n            \"is_notification_disabled\": true,\n            \"is_active\": true\n        },\n        \"custom_branding\": null,\n        \"days_valid\": 0,\n        \"additional_info\": {\n            \"non_editable\": [],\n            \"required\": {\n                \"signers\": [\n                    [\n                        \"email\"\n                    ],\n                    [\n                        \"email\"\n                    ]\n                ]\n            }\n        }\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/storage_policies_assign_yaml.txt",
    "content": "Type: storage_policy_assignment\nID: user_987654321\nStorage Policy:\n    Type: storage_policy\n    ID: '123'\nAssigned To:\n    Type: user\n    ID: '987654321'\n"
  },
  {
    "path": "test/fixtures/output/storage_policies_get_assignment_yaml.txt",
    "content": "Type: storage_policy_assignment\nID: user_987654321\nStorage Policy:\n    Type: storage_policy\n    ID: '123'\nAssigned To:\n    Type: user\n    ID: '987654321'\n"
  },
  {
    "path": "test/fixtures/output/storage_policies_get_yaml.txt",
    "content": "Type: storage_policy\nID: '123'\nName: AWS\n"
  },
  {
    "path": "test/fixtures/output/storage_policies_list_json.txt",
    "content": "[\n    {\n        \"type\": \"storage_policy\",\n        \"id\": \"456\",\n        \"name\": \"Azure\"\n    },\n    {\n        \"type\": \"storage_policy\",\n        \"id\": \"123\",\n        \"name\": \"AWS\"\n    },\n    {\n        \"type\": \"storage_policy\",\n        \"id\": \"456\",\n        \"name\": \"Azure\"\n    },\n    {\n        \"type\": \"storage_policy\",\n        \"id\": \"123\",\n        \"name\": \"AWS\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/storage_policies_lookup_assignment_yaml.txt",
    "content": "Type: storage_policy_assignment\nID: enterprise_77777\nStorage Policy:\n    Type: storage_policy\n    ID: '123'\nAssigned To:\n    Type: enterprise\n    ID: '77777'\n"
  },
  {
    "path": "test/fixtures/output/task_assignments_create_yaml.txt",
    "content": "Type: task_assignment\nID: '12345'\nItem:\n    Type: file\n    ID: '22222'\n    File Version:\n        Type: file_version\n        ID: '222220'\n        SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Sequence ID: '0'\n    ETag: '0'\n    SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Name: Copied file.txt\nAssigned To:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nMessage: ''\nCompleted At: null\nAssigned At: '2018-04-26T19:12:18-07:00'\nReminded At: null\nResolution State: incomplete\nAssigned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\n"
  },
  {
    "path": "test/fixtures/output/task_assignments_get_yaml.txt",
    "content": "Type: task_assignment\nID: '12345'\nItem:\n    Type: file\n    ID: '22222'\n    File Version:\n        Type: file_version\n        ID: '222220'\n        SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Sequence ID: '0'\n    ETag: '0'\n    SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Name: Copied file.txt\nAssigned To:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nMessage: ''\nCompleted At: null\nAssigned At: '2018-04-26T19:12:18-07:00'\nReminded At: null\nResolution State: incomplete\nAssigned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\n"
  },
  {
    "path": "test/fixtures/output/task_assignments_list_json.txt",
    "content": "[\n    {\n        \"type\": \"task_assignment\",\n        \"id\": \"12345\",\n        \"item\": {\n            \"type\": \"file\",\n            \"id\": \"22222\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"222220\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"Copied file.txt\"\n        },\n        \"assigned_to\": {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\"\n        }\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/task_assignments_update_yaml.txt",
    "content": "Type: task_assignment\nID: '12345'\nItem:\n    Type: file\n    ID: '22222'\n    File Version:\n        Type: file_version\n        ID: '222220'\n        SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Sequence ID: '0'\n    ETag: '0'\n    SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Name: Copied file.txt\nAssigned To:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nMessage: Looks good to me!\nCompleted At: '2018-04-26T19:26:23-07:00'\nAssigned At: '2018-04-26T19:12:18-07:00'\nReminded At: null\nResolution State: completed\nAssigned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\n"
  },
  {
    "path": "test/fixtures/output/tasks_create_yaml.txt",
    "content": "Type: task\nID: '11111'\nItem:\n    Type: file\n    ID: '22222'\n    File Version:\n        Type: file_version\n        ID: '222220'\n        SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Sequence ID: '0'\n    ETag: '0'\n    SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Name: Copied file.txt\nDue At: null\nAction: review\nMessage: Please review\nTask Assignment Collection:\n    Total Count: 0\n    Entries: []\nIs Completed: false\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nCreated At: '2018-04-26T11:50:45-07:00'\n"
  },
  {
    "path": "test/fixtures/output/tasks_get_yaml.txt",
    "content": "Type: task\nID: '11111'\nItem:\n    Type: file\n    ID: '22222'\n    File Version:\n        Type: file_version\n        ID: '222220'\n        SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Sequence ID: '0'\n    ETag: '0'\n    SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Name: Copied file.txt\nDue At: null\nAction: review\nMessage: Could you please review this?\nTask Assignment Collection:\n    Total Count: 0\n    Entries: []\nIs Completed: false\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nCreated At: '2018-04-26T11:50:45-07:00'\n"
  },
  {
    "path": "test/fixtures/output/tasks_update_yaml.txt",
    "content": "Type: task\nID: '11111'\nItem:\n    Type: file\n    ID: '22222'\n    File Version:\n        Type: file_version\n        ID: '222220'\n        SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Sequence ID: '0'\n    ETag: '0'\n    SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n    Name: Copied file.txt\nDue At: null\nAction: review\nMessage: Could you please review this?\nTask Assignment Collection:\n    Total Count: 0\n    Entries: []\nIs Completed: false\nCreated By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nCreated At: '2018-04-26T11:50:45-07:00'\n"
  },
  {
    "path": "test/fixtures/output/terms_of_service_create_yaml.txt",
    "content": "Type: terms_of_service\nID: '12345'\nStatus: enabled\nEnterprise:\n    Type: enterprise\n    ID: '1111'\n    Name: Test\nToS Type: managed\nText: test\nCreated At: '2015-06-03T18:01:29-07:00'\nModified At: '2018-04-18T17:44:10-07:00'\n"
  },
  {
    "path": "test/fixtures/output/terms_of_service_get_collaboration_yaml.txt",
    "content": "Type: collaboration\nID: '1234567890'\nAcceptance Requirements:\n    Terms Of Service:\n        Type: terms_of_service\n        ID: '456'\n"
  },
  {
    "path": "test/fixtures/output/terms_of_service_get_user_status_yaml.txt",
    "content": "Type: terms_of_service_user_status\nID: '5678'\nToS:\n    Type: terms_of_service\n    ID: '1234'\nUser:\n    Type: user\n    ID: '7777'\n    Name: Test User\n    Login: test@example.com\nIs Accepted: true\nCreated At: '2015-06-03T18:01:31-07:00'\nModified At: '2017-11-01T13:39:36-07:00'\n"
  },
  {
    "path": "test/fixtures/output/terms_of_service_get_yaml.txt",
    "content": "Type: terms_of_service\nID: '12345'\nStatus: disabled\nEnterprise:\n    Type: enterprise\n    ID: '1111'\n    Name: Test\nToS Type: managed\nText: ''\nCreated At: '2015-06-03T18:01:29-07:00'\nModified At: '2018-04-18T17:44:10-07:00'\n"
  },
  {
    "path": "test/fixtures/output/terms_of_service_list_json.txt",
    "content": "[\n    {\n        \"type\": \"terms_of_service\",\n        \"id\": \"12345\",\n        \"status\": \"disabled\",\n        \"enterprise\": {\n            \"type\": \"enterprise\",\n            \"id\": \"1111\",\n            \"name\": \"Test\"\n        },\n        \"tos_type\": \"managed\",\n        \"text\": \"\",\n        \"created_at\": \"2015-06-03T18:01:29-07:00\",\n        \"modified_at\": \"2018-04-18T17:44:10-07:00\"\n    },\n    {\n        \"type\": \"terms_of_service\",\n        \"id\": \"42343\",\n        \"status\": \"disabled\",\n        \"enterprise\": {\n            \"type\": \"enterprise\",\n            \"id\": \"2222\",\n            \"name\": \"Test\"\n        },\n        \"tos_type\": \"external\",\n        \"text\": \"Example Terms Of Service Text.\",\n        \"created_at\": \"2015-06-03T18:01:29-07:00\",\n        \"modified_at\": \"2017-10-25T11:20:45-07:00\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/terms_of_service_set_user_status_yaml.txt",
    "content": "Type: terms_of_service_user_status\nID: '5678'\nToS:\n    Type: terms_of_service\n    ID: '1234'\nUser:\n    Type: user\n    ID: '7777'\n    Name: Test User\n    Login: test@example.com\nIs Accepted: true\nCreated At: '2015-06-03T18:01:31-07:00'\nModified At: '2017-11-13T12:49:38-08:00'\n"
  },
  {
    "path": "test/fixtures/output/terms_of_service_update_yaml.txt",
    "content": "Type: terms_of_service\nID: '12345'\nStatus: enabled\nEnterprise:\n    Type: enterprise\n    ID: '1111'\n    Name: Test\nToS Type: managed\nText: test\nCreated At: '2015-06-03T18:01:29-07:00'\nModified At: '2018-04-18T17:44:10-07:00'\n"
  },
  {
    "path": "test/fixtures/output/trash_list_json.txt",
    "content": "[\n    {\n        \"type\": \"file\",\n        \"id\": \"2701979016\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"sha1\": \"9d976863fc849f6061ecf9736710bd9c2bce488c\",\n        \"name\": \"file Tue Jul 24 145436 2012KWPX5S.csv\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"2698211586\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"sha1\": \"09b0e2e9760caf7448c702db34ea001f356f1197\",\n        \"name\": \"file Tue Jul 24 010055 20129Z6GS3.csv\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"2701979019\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"sha1\": \"9d976863fc849f6061ecf9736710bd9c2bce488c\",\n        \"name\": \"file Tue Jul 24 145436 2012KWPX5S.csv\"\n    },\n    {\n        \"type\": \"file\",\n        \"id\": \"2698211570\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"sha1\": \"09b0e2e9760caf7448c702db34ea001f356f1197\",\n        \"name\": \"file Tue Jul 24 010055 20129Z6GS3.csv\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/users_add_email_alias_yaml.txt",
    "content": "Type: email_alias\nID: '1234'\nIs Confirmed: true\nEmail: dglover2@example.com\n"
  },
  {
    "path": "test/fixtures/output/users_create_yaml.txt",
    "content": "Type: user\nID: '77777'\nName: Another Test User\nLogin: anothertestuser@example.com\nCreated At: '2018-04-26T20:19:51-07:00'\nModified At: '2018-04-26T20:19:52-07:00'\nLanguage: en\nTimezone: America/Los_Angeles\nSpace Amount: 10737418240\nSpace Used: 0\nMax Upload Size: 5368709120\nStatus: active\nJob Title: ''\nPhone: '1234567890'\nAddress: ''\nAvatar URL: https://app.box.com/api/avatar/large/deprecated\n"
  },
  {
    "path": "test/fixtures/output/users_get_email_aliases_json.txt",
    "content": "[\n    {\n        \"type\": \"email_alias\",\n        \"id\": \"1234\",\n        \"is_confirmed\": true,\n        \"email\": \"dglover2@example.com\"\n    },\n    {\n        \"type\": \"email_alias\",\n        \"id\": \"1235\",\n        \"is_confirmed\": true,\n        \"email\": \"dglover3@example.com\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/users_get_email_aliases_table.txt",
    "content": "----- Email Alias 1234 -----\nType: email_alias\nID: '1234'\nIs Confirmed: true\nEmail: dglover2@example.com\n\n----- Email Alias 1235 -----\nType: email_alias\nID: '1235'\nIs Confirmed: true\nEmail: dglover3@example.com\n"
  },
  {
    "path": "test/fixtures/output/users_get_yaml.txt",
    "content": "Type: user\nID: '33333'\nName: Test User\nLogin: testuser@example.com\nCreated At: '2016-11-09T15:57:20-08:00'\nModified At: '2018-04-25T17:07:47-07:00'\nLanguage: en\nTimezone: America/Los_Angeles\nSpace Amount: 1000000000000000\nSpace Used: 38243356\nMax Upload Size: 5368709120\nStatus: active\nJob Title: ''\nPhone: 555-555-5555\nAddress: ''\nAvatar URL: https://app.box.com/api/avatar/large/deprecated\n"
  },
  {
    "path": "test/fixtures/output/users_invite_user_yaml.txt",
    "content": "Type: user\nID: '33333'\nName: Test User\nLogin: testuser@example.com\nCreated At: '2016-11-09T15:57:20-08:00'\nModified At: '2018-04-25T17:07:47-07:00'\nLanguage: en\nTimezone: America/Los_Angeles\nSpace Amount: 1000000000000000\nSpace Used: 38243356\nMax Upload Size: 5368709120\nStatus: active\nJob Title: ''\nPhone: 555-555-5555\nAddress: ''\nAvatar URL: https://app.box.com/api/avatar/large/deprecated\n"
  },
  {
    "path": "test/fixtures/output/users_list_groups_json.txt",
    "content": "[\n    {\n        \"type\": \"group_membership\",\n        \"id\": \"1560354\",\n        \"user\": {\n            \"type\": \"user\",\n            \"id\": \"13130406\",\n            \"name\": \"Alison Wonderland\",\n            \"login\": \"alice@gmail.com\"\n        },\n        \"group\": {\n            \"type\": \"group\",\n            \"id\": \"119720\",\n            \"name\": \"family\"\n        },\n        \"role\": \"member\"\n    },\n    {\n        \"type\": \"group_membership\",\n        \"id\": \"1560354\",\n        \"user\": {\n            \"type\": \"user\",\n            \"id\": \"13130406\",\n            \"name\": \"Alison Wonderland\",\n            \"login\": \"alice@gmail.com\"\n        },\n        \"group\": {\n            \"type\": \"group\",\n            \"id\": \"119723\",\n            \"name\": \"family\"\n        },\n        \"role\": \"member\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/users_list_json.txt",
    "content": "[\n    {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\",\n        \"created_at\": \"2016-11-09T15:57:20-08:00\",\n        \"modified_at\": \"2018-04-26T19:46:19-07:00\",\n        \"language\": \"en\",\n        \"timezone\": \"America/Los_Angeles\",\n        \"space_amount\": 1000000000000000,\n        \"space_used\": 38243356,\n        \"max_upload_size\": 5368709120,\n        \"status\": \"active\",\n        \"job_title\": \"CEO\",\n        \"phone\": \"(555) 555-5555\",\n        \"address\": \"\",\n        \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n    },\n    {\n        \"type\": \"user\",\n        \"id\": \"44444\",\n        \"name\": \"Test User 2\",\n        \"login\": \"testuser2@example.com\",\n        \"created_at\": \"2016-11-16T21:46:24-08:00\",\n        \"modified_at\": \"2017-12-21T14:12:42-08:00\",\n        \"language\": \"en\",\n        \"timezone\": \"America/Los_Angeles\",\n        \"space_amount\": 1000000000000000,\n        \"space_used\": 0,\n        \"max_upload_size\": 5368709120,\n        \"status\": \"active\",\n        \"job_title\": \"\",\n        \"phone\": \"\",\n        \"address\": \"\",\n        \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n    },\n    {\n        \"type\": \"user\",\n        \"id\": \"55555\",\n        \"name\": \"Test User 3\",\n        \"login\": \"testuser3@example.com\",\n        \"created_at\": \"2016-12-07T16:49:13-08:00\",\n        \"modified_at\": \"2017-12-21T14:12:42-08:00\",\n        \"language\": \"en\",\n        \"timezone\": \"America/Los_Angeles\",\n        \"space_amount\": 1000000000000000,\n        \"space_used\": 790226181,\n        \"max_upload_size\": 5368709120,\n        \"status\": \"active\",\n        \"job_title\": \"\",\n        \"phone\": \"\",\n        \"address\": \"\",\n        \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n    },\n    {\n        \"type\": \"user\",\n        \"id\": \"333334\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\",\n        \"created_at\": \"2016-11-09T15:57:20-08:00\",\n        \"modified_at\": \"2018-04-26T19:46:19-07:00\",\n        \"language\": \"en\",\n        \"timezone\": \"America/Los_Angeles\",\n        \"space_amount\": 1000000000000000,\n        \"space_used\": 38243356,\n        \"max_upload_size\": 5368709120,\n        \"status\": \"active\",\n        \"job_title\": \"CEO\",\n        \"phone\": \"(555) 555-5555\",\n        \"address\": \"\",\n        \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n    },\n    {\n        \"type\": \"user\",\n        \"id\": \"444445\",\n        \"name\": \"Test User 2\",\n        \"login\": \"testuser2@example.com\",\n        \"created_at\": \"2016-11-16T21:46:24-08:00\",\n        \"modified_at\": \"2017-12-21T14:12:42-08:00\",\n        \"language\": \"en\",\n        \"timezone\": \"America/Los_Angeles\",\n        \"space_amount\": 1000000000000000,\n        \"space_used\": 0,\n        \"max_upload_size\": 5368709120,\n        \"status\": \"active\",\n        \"job_title\": \"\",\n        \"phone\": \"\",\n        \"address\": \"\",\n        \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n    },\n    {\n        \"type\": \"user\",\n        \"id\": \"555556\",\n        \"name\": \"Test User 3\",\n        \"login\": \"testuser3@example.com\",\n        \"created_at\": \"2016-12-07T16:49:13-08:00\",\n        \"modified_at\": \"2017-12-21T14:12:42-08:00\",\n        \"language\": \"en\",\n        \"timezone\": \"America/Los_Angeles\",\n        \"space_amount\": 1000000000000000,\n        \"space_used\": 790226181,\n        \"max_upload_size\": 5368709120,\n        \"status\": \"active\",\n        \"job_title\": \"\",\n        \"phone\": \"\",\n        \"address\": \"\",\n        \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/users_move_root_content_yaml.txt",
    "content": "Type: folder\nID: '0'\nSequence ID: null\nETag: null\nName: All Files\nCreated At: null\nModified At: null\nDescription: ''\nSize: 8183737\nPath Collection:\n    Total Count: 0\n    Entries: []\nCreated By:\n    Type: user\n    ID: ''\n    Name: ''\n    Login: ''\nModified By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nTrashed At: null\nPurged At: null\nContent Created At: null\nContent Modified At: null\nOwned By:\n    Type: user\n    ID: '33333'\n    Name: Test User\n    Login: testuser@example.com\nShared Link: null\nFolder Upload Email: null\nParent: null\nItem Status: active\nItem Collection:\n    Total Count: 6\n    Entries:\n        -\n            Type: folder\n            ID: '44444'\n            Sequence ID: '1'\n            ETag: '1'\n            Name: Collab Folder\n        -\n            Type: folder\n            ID: '55555'\n            Sequence ID: '0'\n            ETag: '0'\n            Name: Copied Folder\n        -\n            Type: folder\n            ID: '66666'\n            Sequence ID: '0'\n            ETag: '0'\n            Name: SDK Test Folder\n        -\n            Type: folder\n            ID: '77777'\n            Sequence ID: '1'\n            ETag: '1'\n            Name: Test Folder\n        -\n            Type: file\n            ID: '88888'\n            File Version:\n                Type: file_version\n                ID: '888880'\n                SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n            Sequence ID: '0'\n            ETag: '0'\n            SHA1: 6afc05eae22e994f1c7dd48e58f8895dd9028223\n            Name: Copied file.txt\n        -\n            Type: file\n            ID: '99999'\n            File Version:\n                Type: file_version\n                ID: '999990'\n                SHA1: 97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\n            Sequence ID: '9'\n            ETag: '9'\n            SHA1: 97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\n            Name: test file.txt\n    Offset: 0\n    Limit: 100\n    Order:\n        -\n            By: type\n            Direction: ASC\n        -\n            By: name\n            Direction: ASC\n"
  },
  {
    "path": "test/fixtures/output/users_search_fields_json.txt",
    "content": "[\n    {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\"\n    },\n    {\n        \"type\": \"user\",\n        \"id\": \"44444\",\n        \"name\": \"Test User 2\"\n    },\n    {\n        \"type\": \"user\",\n        \"id\": \"55555\",\n        \"name\": \"Test User 3\"\n    },\n    {\n        \"type\": \"user\",\n        \"id\": \"333334\",\n        \"name\": \"Test User\"\n    },\n    {\n        \"type\": \"user\",\n        \"id\": \"444445\",\n        \"name\": \"Test User 2\"\n    },\n    {\n        \"type\": \"user\",\n        \"id\": \"555556\",\n        \"name\": \"Test User 3\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/users_search_json.txt",
    "content": "[\n    {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\",\n        \"created_at\": \"2016-11-09T15:57:20-08:00\",\n        \"modified_at\": \"2018-04-26T19:46:19-07:00\",\n        \"language\": \"en\",\n        \"timezone\": \"America/Los_Angeles\",\n        \"space_amount\": 1000000000000000,\n        \"space_used\": 38243356,\n        \"max_upload_size\": 5368709120,\n        \"status\": \"active\",\n        \"job_title\": \"CEO\",\n        \"phone\": \"(555) 555-5555\",\n        \"address\": \"\",\n        \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n    },\n    {\n        \"type\": \"user\",\n        \"id\": \"44444\",\n        \"name\": \"Test User 2\",\n        \"login\": \"testuser2@example.com\",\n        \"created_at\": \"2016-11-16T21:46:24-08:00\",\n        \"modified_at\": \"2017-12-21T14:12:42-08:00\",\n        \"language\": \"en\",\n        \"timezone\": \"America/Los_Angeles\",\n        \"space_amount\": 1000000000000000,\n        \"space_used\": 0,\n        \"max_upload_size\": 5368709120,\n        \"status\": \"active\",\n        \"job_title\": \"\",\n        \"phone\": \"\",\n        \"address\": \"\",\n        \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n    },\n    {\n        \"type\": \"user\",\n        \"id\": \"55555\",\n        \"name\": \"Test User 3\",\n        \"login\": \"testuser3@example.com\",\n        \"created_at\": \"2016-12-07T16:49:13-08:00\",\n        \"modified_at\": \"2017-12-21T14:12:42-08:00\",\n        \"language\": \"en\",\n        \"timezone\": \"America/Los_Angeles\",\n        \"space_amount\": 1000000000000000,\n        \"space_used\": 790226181,\n        \"max_upload_size\": 5368709120,\n        \"status\": \"active\",\n        \"job_title\": \"\",\n        \"phone\": \"\",\n        \"address\": \"\",\n        \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n    },\n    {\n        \"type\": \"user\",\n        \"id\": \"333334\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\",\n        \"created_at\": \"2016-11-09T15:57:20-08:00\",\n        \"modified_at\": \"2018-04-26T19:46:19-07:00\",\n        \"language\": \"en\",\n        \"timezone\": \"America/Los_Angeles\",\n        \"space_amount\": 1000000000000000,\n        \"space_used\": 38243356,\n        \"max_upload_size\": 5368709120,\n        \"status\": \"active\",\n        \"job_title\": \"CEO\",\n        \"phone\": \"(555) 555-5555\",\n        \"address\": \"\",\n        \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n    },\n    {\n        \"type\": \"user\",\n        \"id\": \"444445\",\n        \"name\": \"Test User 2\",\n        \"login\": \"testuser2@example.com\",\n        \"created_at\": \"2016-11-16T21:46:24-08:00\",\n        \"modified_at\": \"2017-12-21T14:12:42-08:00\",\n        \"language\": \"en\",\n        \"timezone\": \"America/Los_Angeles\",\n        \"space_amount\": 1000000000000000,\n        \"space_used\": 0,\n        \"max_upload_size\": 5368709120,\n        \"status\": \"active\",\n        \"job_title\": \"\",\n        \"phone\": \"\",\n        \"address\": \"\",\n        \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n    },\n    {\n        \"type\": \"user\",\n        \"id\": \"555556\",\n        \"name\": \"Test User 3\",\n        \"login\": \"testuser3@example.com\",\n        \"created_at\": \"2016-12-07T16:49:13-08:00\",\n        \"modified_at\": \"2017-12-21T14:12:42-08:00\",\n        \"language\": \"en\",\n        \"timezone\": \"America/Los_Angeles\",\n        \"space_amount\": 1000000000000000,\n        \"space_used\": 790226181,\n        \"max_upload_size\": 5368709120,\n        \"status\": \"active\",\n        \"job_title\": \"\",\n        \"phone\": \"\",\n        \"address\": \"\",\n        \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/users_update_yaml.txt",
    "content": "Type: user\nID: '33333'\nName: Test User\nLogin: testuser@example.com\nCreated At: '2016-11-09T15:57:20-08:00'\nModified At: '2018-04-25T17:07:47-07:00'\nLanguage: en\nTimezone: America/Los_Angeles\nSpace Amount: 1000000000000000\nSpace Used: 38243356\nMax Upload Size: 5368709120\nStatus: active\nJob Title: CEO\nPhone: (555) 555-5555\nAddress: ''\nAvatar URL: https://app.box.com/api/avatar/large/deprecated\n"
  },
  {
    "path": "test/fixtures/output/watermarking_apply_yaml.txt",
    "content": "Watermark:\n    Created At: '2018-04-24T17:12:19-07:00'\n    Modified At: '2018-04-24T17:12:19-07:00'\n"
  },
  {
    "path": "test/fixtures/output/watermarking_get_yaml.txt",
    "content": "Watermark:\n    Created At: '2018-04-24T17:12:19-07:00'\n    Modified At: '2018-04-24T17:12:19-07:00'\n"
  },
  {
    "path": "test/fixtures/output/web_links_create_yaml.txt",
    "content": "Type: web_link\nID: '6743065'\nSequence ID: '0'\nETag: '0'\nName: Box Website!\nURL: https://www.box.com\nCreated By:\n    Type: user\n    ID: '10523870'\n    Name: Ted Blosser\n    Login: ted+demo@example.com\nCreated At: '2015-05-07T15:00:01-07:00'\nModified At: '2015-05-07T15:00:01-07:00'\nParent:\n    Type: folder\n    ID: '848123342'\n    Sequence ID: '1'\n    ETag: '1'\n    Name: Documentation\nDescription: Cloud Content Management\nItem Status: active\nTrashed At: null\nPurged At: null\nShared Link: null\nPath Collection:\n    Total Count: 2\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\n        -\n            Type: folder\n            ID: '848123342'\n            Sequence ID: '1'\n            ETag: '1'\n            Name: Documentation\nModified By:\n    Type: user\n    ID: '10523870'\n    Name: Ted Blosser\n    Login: ted+demo@example.com\nOwned By:\n    Type: user\n    ID: '10523870'\n    Name: Ted Blosser\n    Login: ted+demo@example.com\n"
  },
  {
    "path": "test/fixtures/output/web_links_get_yaml.txt",
    "content": "Type: web_link\nID: '6742981'\nSequence ID: '0'\nETag: '0'\nName: Box Website\nURL: https://www.box.com\nCreated By:\n    Type: user\n    ID: '10523870'\n    Name: Ted Blosser\n    Login: ted+demo@example.com\nCreated At: '2015-05-07T14:31:16-07:00'\nModified At: '2015-05-07T14:31:16-07:00'\nParent:\n    Type: folder\n    ID: '848123342'\n    Sequence ID: '1'\n    ETag: '1'\n    Name: Documentation\nDescription: Cloud Content Management\nItem Status: active\nTrashed At: null\nPurged At: null\nShared Link: null\nPath Collection:\n    Total Count: 2\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\n        -\n            Type: folder\n            ID: '848123342'\n            Sequence ID: '1'\n            ETag: '1'\n            Name: Documentation\nModified By:\n    Type: user\n    ID: '10523870'\n    Name: Ted Blosser\n    Login: ted+demo@example.com\nOwned By:\n    Type: user\n    ID: '10523870'\n    Name: Ted Blosser\n    Login: ted+demo@example.com\n"
  },
  {
    "path": "test/fixtures/output/web_links_move_yaml.txt",
    "content": "Type: web_link\nID: '6742981'\nSequence ID: '2'\nETag: '2'\nName: Box Marketing Web Page\nURL: https://www.box.com\nCreated By:\n    Type: user\n    ID: '10523870'\n    Name: Ted Blosser\n    Login: ted+demo@example.com\nCreated At: '2015-05-07T14:31:16-07:00'\nModified At: '2015-05-07T15:45:04-07:00'\nParent:\n    Type: folder\n    ID: '848123342'\n    Sequence ID: '1'\n    ETag: '1'\n    Name: Documentation\nDescription: Cloud Content Management\nItem Status: active\nTrashed At: null\nPurged At: null\nShared Link: null\nPath Collection:\n    Total Count: 2\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\n        -\n            Type: folder\n            ID: '848123342'\n            Sequence ID: '1'\n            ETag: '1'\n            Name: Documentation\nModified By:\n    Type: user\n    ID: '10523870'\n    Name: Ted Blosser\n    Login: ted+demo@example.com\nOwned By:\n    Type: user\n    ID: '10523870'\n    Name: Ted Blosser\n    Login: ted+demo@example.com\n"
  },
  {
    "path": "test/fixtures/output/web_links_update_yaml.txt",
    "content": "Type: web_link\nID: '6742981'\nSequence ID: '2'\nETag: '2'\nName: Box Marketing Web Page\nURL: https://www.box.com\nCreated By:\n    Type: user\n    ID: '10523870'\n    Name: Ted Blosser\n    Login: ted+demo@example.com\nCreated At: '2015-05-07T14:31:16-07:00'\nModified At: '2015-05-07T15:45:04-07:00'\nParent:\n    Type: folder\n    ID: '848123342'\n    Sequence ID: '1'\n    ETag: '1'\n    Name: Documentation\nDescription: Cloud Content Management\nItem Status: active\nTrashed At: null\nPurged At: null\nShared Link: null\nPath Collection:\n    Total Count: 2\n    Entries:\n        -\n            Type: folder\n            ID: '0'\n            Sequence ID: null\n            ETag: null\n            Name: All Files\n        -\n            Type: folder\n            ID: '848123342'\n            Sequence ID: '1'\n            ETag: '1'\n            Name: Documentation\nModified By:\n    Type: user\n    ID: '10523870'\n    Name: Ted Blosser\n    Login: ted+demo@example.com\nOwned By:\n    Type: user\n    ID: '10523870'\n    Name: Ted Blosser\n    Login: ted+demo@example.com\n"
  },
  {
    "path": "test/fixtures/output/webhooks_create_yaml.txt",
    "content": "ID: '1234'\nType: webhook\nTarget:\n    ID: '5016243669'\n    Type: file\nCreated By:\n    Type: user\n    ID: '2030392653'\n    Name: John Q. Developer\n    Login: johnq@dev.name\nCreated At: '2016-05-09T17:41:27-07:00'\nAddress: https://dev.name/actions/file_changed\nTriggers:\n    - FILE.DOWNLOADED\n    - FILE.UPLOADED\n"
  },
  {
    "path": "test/fixtures/output/webhooks_get_yaml.txt",
    "content": "ID: '1234'\nType: webhook\nTarget:\n    ID: '5018848529'\n    Type: file\nCreated By:\n    Type: user\n    ID: '2030392653'\n    Name: John Q. Developer\n    Login: johnq@example.net\nCreated At: '2016-05-04T18:51:45-07:00'\nAddress: https://example.net/actions/file_changed\nTriggers:\n    - FILE.PREVIEWED\n"
  },
  {
    "path": "test/fixtures/output/webhooks_list_json.txt",
    "content": "[\n    {\n        \"id\": \"4161\",\n        \"type\": \"webhook\",\n        \"target\": {\n            \"id\": \"5018326685\",\n            \"type\": \"folder\"\n        }\n    },\n    {\n        \"id\": \"4165\",\n        \"type\": \"webhook\",\n        \"target\": {\n            \"id\": \"5016243669\",\n            \"type\": \"file\"\n        }\n    },\n    {\n        \"id\": \"41611\",\n        \"type\": \"webhook\",\n        \"target\": {\n            \"id\": \"5018326685\",\n            \"type\": \"folder\"\n        }\n    },\n    {\n        \"id\": \"41651\",\n        \"type\": \"webhook\",\n        \"target\": {\n            \"id\": \"5016243669\",\n            \"type\": \"file\"\n        }\n    }\n]\n"
  },
  {
    "path": "test/fixtures/output/webhooks_update_yaml.txt",
    "content": "ID: '1234'\nType: webhook\nTarget:\n    ID: '5016243669'\n    Type: file\nCreated By:\n    Type: user\n    ID: '2030392653'\n    Name: John Q. Developer\n    Login: johnq@dev.name\nCreated At: '2016-05-09T17:41:27-07:00'\nAddress: https://dev.name/actions/file_changed\nTriggers:\n    - FILE.DOWNLOADED\n    - FILE.UPLOADED\n"
  },
  {
    "path": "test/fixtures/pagination/get_files_id_versions_marker.json",
    "content": "{\n    \"total_count\": 2,\n    \"entries\": [\n        {\n            \"type\": \"file_version\",\n            \"id\": \"11111\",\n            \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n            \"name\": \"test file.txt\",\n            \"size\": 16,\n            \"created_at\": \"2016-12-07T15:59:32-08:00\",\n            \"modified_at\": \"2016-12-07T15:59:32-08:00\",\n            \"modified_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"trashed_at\": null,\n            \"purged_at\": null\n        },\n        {\n            \"type\": \"file_version\",\n            \"id\": \"22222\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"test file.txt\",\n            \"size\": 9,\n            \"created_at\": \"2016-12-07T15:53:59-08:00\",\n            \"modified_at\": \"2016-12-07T15:53:59-08:00\",\n            \"modified_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"trashed_at\": null,\n            \"purged_at\": null\n        }\n    ],\n    \"limit\": 2,\n    \"offset\": 0,\n    \"marker\": null\n}"
  },
  {
    "path": "test/fixtures/pagination/get_folders_id_items_marker.json",
    "content": "{\n    \"total_count\": 2,\n    \"entries\": [\n        {\n            \"type\": \"folder\",\n            \"id\": \"11111\",\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"name\": \"SDK Test Folder\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"22222\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"222220\",\n                \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n            },\n            \"sequence_id\": \"9\",\n            \"etag\": \"9\",\n            \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n            \"name\": \"test file.txt\"\n        }\n    ],\n    \"marker\": null,\n    \"order\": [\n        {\n            \"by\": \"type\",\n            \"direction\": \"ASC\"\n        },\n        {\n            \"by\": \"name\",\n            \"direction\": \"ASC\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/recent-items/get_recent_items_page_1.json",
    "content": "{\n    \"next_marker\": \"ZDF123\",\n    \"limit\": 3,\n    \"order\": {\n        \"by\": \"interacted_at\",\n        \"direction\": \"DESC\"\n    },\n    \"entries\": [\n        {\n            \"type\": \"recent_item\",\n            \"interaction_type\": \"item_preview\",\n            \"interacted_at\": \"2018-04-25T17:07:44-07:00\",\n            \"item\": {\n                \"type\": \"file\",\n                \"id\": \"11111\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"111110\",\n                    \"sha1\": \"3c0b046ef81f262cb5b2e417b45c7aaa507a5628\"\n                },\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"sha1\": \"3c0b046ef81f262cb5b2e417b45c7aaa507a5628\",\n                \"name\": \"Instruction Manual.pdf\"\n            },\n            \"interaction_shared_link\": null\n        },\n        {\n            \"type\": \"recent_item\",\n            \"interaction_type\": \"item_preview\",\n            \"interacted_at\": \"2018-04-24T17:22:11-07:00\",\n            \"item\": {\n                \"type\": \"file\",\n                \"id\": \"22222\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"222220\",\n                    \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n                },\n                \"sequence_id\": \"9\",\n                \"etag\": \"9\",\n                \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n                \"name\": \"test file.txt\"\n            },\n            \"interaction_shared_link\": null\n        },\n        {\n            \"type\": \"recent_item\",\n            \"interaction_type\": \"item_preview\",\n            \"interacted_at\": \"2018-04-24T16:49:13-07:00\",\n            \"item\": {\n                \"type\": \"file\",\n                \"id\": \"44444\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"444440\",\n                    \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n                },\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n                \"name\": \"Copied file.txt\"\n            },\n            \"interaction_shared_link\": null\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/recent-items/get_recent_items_page_2.json",
    "content": "{\n    \"next_marker\": \"\",\n    \"limit\": 3,\n    \"order\": {\n        \"by\": \"interacted_at\",\n        \"direction\": \"DESC\"\n    },\n    \"entries\": [\n        {\n            \"type\": \"recent_item\",\n            \"interaction_type\": \"item_preview\",\n            \"interacted_at\": \"2018-04-25T17:07:44-07:00\",\n            \"item\": {\n                \"type\": \"file\",\n                \"id\": \"11112\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"111110\",\n                    \"sha1\": \"3c0b046ef81f262cb5b2e417b45c7aaa507a5628\"\n                },\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"sha1\": \"3c0b046ef81f262cb5b2e417b45c7aaa507a5628\",\n                \"name\": \"Instruction Manual.pdf\"\n            },\n            \"interaction_shared_link\": null\n        },\n        {\n            \"type\": \"recent_item\",\n            \"interaction_type\": \"item_preview\",\n            \"interacted_at\": \"2018-04-24T17:22:11-07:00\",\n            \"item\": {\n                \"type\": \"file\",\n                \"id\": \"22223\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"222220\",\n                    \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n                },\n                \"sequence_id\": \"9\",\n                \"etag\": \"9\",\n                \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n                \"name\": \"test file.txt\"\n            },\n            \"interaction_shared_link\": null\n        },\n        {\n            \"type\": \"recent_item\",\n            \"interaction_type\": \"item_preview\",\n            \"interacted_at\": \"2018-04-24T16:49:13-07:00\",\n            \"item\": {\n                \"type\": \"file\",\n                \"id\": \"44445\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"444440\",\n                    \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n                },\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n                \"name\": \"Copied file.txt\"\n            },\n            \"interaction_shared_link\": null\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/retention-policies/get_file_version_retentions_id.json",
    "content": "{\n    \"type\": \"file_version_retention\",\n    \"id\": \"444444\",\n    \"applied_at\": \"2016-12-08T11:22:18-08:00\",\n    \"disposition_at\": \"2106-02-06T22:28:15-08:00\",\n    \"winning_retention_policy\": {\n        \"type\": \"retention_policy\",\n        \"id\": \"22222\",\n        \"policy_name\": \"Retain Times Infinity\"\n    },\n    \"file_version\": {\n        \"type\": \"file_version\",\n        \"id\": \"111110\",\n        \"sha1\": null\n    },\n    \"file\": {\n        \"type\": \"file\",\n        \"id\": \"11111\",\n        \"etag\": \"0\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/retention-policies/get_file_version_retentions_page_1.json",
    "content": "{\n\t\"next_marker\": \"ZAD345\",\n\t\"entries\": [\n\t\t{\n\t\t\t\"type\": \"file_version_retention\",\n\t\t\t\"id\": \"111111\"\n        },\n\t\t{\n\t\t\t\"type\": \"file_version_retention\",\n\t\t\t\"id\": \"222222\"\n        },\n\t\t{\n\t\t\t\"type\": \"file_version_retention\",\n\t\t\t\"id\": \"333333\"\n        },\n\t\t{\n\t\t\t\"type\": \"file_version_retention\",\n\t\t\t\"id\": \"444444\"\n        }\n    ],\n\t\"limit\": 100,\n\t\"order\": [\n\t\t{\n\t\t\t\"by\": \"file_version_id\",\n\t\t\t\"direction\": \"ASC\"\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/retention-policies/get_file_version_retentions_page_2.json",
    "content": "{\n\t\"entries\": [\n\t\t{\n\t\t\t\"type\": \"file_version_retention\",\n\t\t\t\"id\": \"111112\"\n        },\n\t\t{\n\t\t\t\"type\": \"file_version_retention\",\n\t\t\t\"id\": \"222223\"\n        },\n\t\t{\n\t\t\t\"type\": \"file_version_retention\",\n\t\t\t\"id\": \"333334\"\n        },\n\t\t{\n\t\t\t\"type\": \"file_version_retention\",\n\t\t\t\"id\": \"444445\"\n        }\n    ],\n\t\"limit\": 100,\n\t\"order\": [\n\t\t{\n\t\t\t\"by\": \"file_version_id\",\n\t\t\t\"direction\": \"ASC\"\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/retention-policies/get_file_versions_under_retention_page_1.json",
    "content": "{\n\t\"entries\": [\n\t\t{\n\t\t\t\"id\": 12345,\n\t\t\t\"etag\": 1,\n\t\t\t\"type\": \"file_version\",\n\t\t\t\"sequence_id\": 3,\n\t\t\t\"name\": \"Contract.pdf\",\n\t\t\t\"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\",\n\t\t\t\"file_version\": {\n\t\t\t\t\"id\": 12345,\n\t\t\t\t\"type\": \"file_version\",\n\t\t\t\t\"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n\t\t\t},\n\t\t\t\"applied_at\": \"2012-12-12T10:53:43-08:00\"\n\t\t}\n\t],\n\t\"limit\": 1000,\n\t\"next_marker\": \"ZAD345\"\n}\n"
  },
  {
    "path": "test/fixtures/retention-policies/get_file_versions_under_retention_page_2.json",
    "content": "{\n\t\"entries\": [\n\t\t{\n\t\t\t\"id\": 67890,\n\t\t\t\"etag\": 1,\n\t\t\t\"type\": \"file_version\",\n\t\t\t\"sequence_id\": 3,\n\t\t\t\"name\": \"Document.pdf\",\n\t\t\t\"sha1\": \"018EE5D1D1E0D0727CED62CA5F1B71F6F07AB96B\",\n\t\t\t\"file_version\": {\n\t\t\t\t\"id\": 67890,\n\t\t\t\t\"type\": \"file_version\",\n\t\t\t\t\"sha1\": \"18CA54DC8372620C1E46ADE6D56FF220A19D01F8\"\n\t\t\t},\n\t\t\t\"applied_at\": \"2012-12-12T10:53:43-08:00\"\n\t\t}\n\t],\n\t\"limit\": 1000\n}\n"
  },
  {
    "path": "test/fixtures/retention-policies/get_files_under_retention_page_1.json",
    "content": "{\n\t\"entries\": [\n\t\t{\n\t\t\t\"id\": 12345,\n\t\t\t\"etag\": 1,\n\t\t\t\"type\": \"file\",\n\t\t\t\"sequence_id\": 3,\n\t\t\t\"name\": \"Contract.pdf\",\n\t\t\t\"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\",\n\t\t\t\"file_version\": {\n\t\t\t\t\"id\": 123456,\n\t\t\t\t\"type\": \"file_version\",\n\t\t\t\t\"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n\t\t\t},\n\t\t\t\"applied_at\": \"2012-12-12T10:53:43-08:00\"\n\t\t}\n\t],\n\t\"limit\": 1000,\n\t\"next_marker\": \"ZAD345\"\n}"
  },
  {
    "path": "test/fixtures/retention-policies/get_files_under_retention_page_2.json",
    "content": "{\n\t\"entries\": [\n\t\t{\n\t\t\t\"id\": 6789,\n\t\t\t\"etag\": 1,\n\t\t\t\"type\": \"file\",\n\t\t\t\"sequence_id\": 3,\n\t\t\t\"name\": \"Document.pdf\",\n\t\t\t\"sha1\": \"3C363836CF4E16666669A25DA280A1865C2D2874\",\n\t\t\t\"file_version\": {\n\t\t\t\t\"id\": 67890,\n\t\t\t\t\"type\": \"file_version\",\n\t\t\t\t\"sha1\": \"2813c90c8178bf651a75ca1b96f015ce3def166b\"\n\t\t\t},\n\t\t\t\"applied_at\": \"2012-12-12T10:53:43-08:00\"\n\t\t}\n\t],\n\t\"limit\": 1000\n}"
  },
  {
    "path": "test/fixtures/retention-policies/get_retention_policies_id.json",
    "content": "{\n    \"type\": \"retention_policy\",\n    \"id\": \"11111\",\n    \"policy_name\": \"Financial Records\",\n    \"policy_type\": \"finite\",\n    \"retention_length\": \"365\",\n    \"disposition_action\": \"remove_retention\",\n    \"can_owner_extend_retention\": false,\n    \"status\": \"active\",\n    \"are_owners_notified\": false,\n    \"custom_notification_recipients\": [],\n    \"assignment_counts\": {\n        \"enterprise\": 0,\n        \"folder\": 0,\n        \"metadata_template\": 0\n    },\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"created_at\": \"2018-04-25T18:29:40-07:00\",\n    \"modified_at\": \"2018-04-25T18:29:40-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/retention-policies/get_retention_policies_id_assignments_page_1.json",
    "content": "{\n    \"entries\": [\n        {\n            \"type\": \"retention_policy_assignment\",\n            \"id\": \"12345\"\n        }\n    ],\n\t\t\"next_marker\": \"ZDE456\",\n    \"limit\": 1000\n}"
  },
  {
    "path": "test/fixtures/retention-policies/get_retention_policies_id_assignments_page_2.json",
    "content": "{\n    \"entries\": [\n        {\n            \"type\": \"retention_policy_assignment\",\n            \"id\": \"123456\"\n        }\n    ],\n    \"limit\": 1000\n}"
  },
  {
    "path": "test/fixtures/retention-policies/get_retention_policies_page_1.json",
    "content": "{\n\t\"entries\": [\n\t\t{\n\t\t\t\"type\": \"retention_policy\",\n\t\t\t\"id\": \"44444\",\n\t\t\t\"policy_name\": \"My Policy\"\n        },\n\t\t{\n\t\t\t\"type\": \"retention_policy\",\n\t\t\t\"id\": \"33333\",\n\t\t\t\"policy_name\": \"Retain Forever\"\n        },\n\t\t{\n\t\t\t\"type\": \"retention_policy\",\n\t\t\t\"id\": \"11111\",\n\t\t\t\"policy_name\": \"Retained Financial Records\"\n        },\n\t\t{\n\t\t\t\"type\": \"retention_policy\",\n\t\t\t\"id\": \"22222\",\n\t\t\t\"policy_name\": \"Very Short Retention\"\n        }\n    ],\n\t\"next_marker\": \"ZDE345\",\n\t\"limit\": 1000\n}\n"
  },
  {
    "path": "test/fixtures/retention-policies/get_retention_policies_page_2.json",
    "content": "{\n\t\"entries\": [\n\t\t{\n\t\t\t\"type\": \"retention_policy\",\n\t\t\t\"id\": \"44445\",\n\t\t\t\"policy_name\": \"My Policy\"\n        },\n\t\t{\n\t\t\t\"type\": \"retention_policy\",\n\t\t\t\"id\": \"33334\",\n\t\t\t\"policy_name\": \"Retain Forever\"\n        },\n\t\t{\n\t\t\t\"type\": \"retention_policy\",\n\t\t\t\"id\": \"11112\",\n\t\t\t\"policy_name\": \"Retained Financial Records\"\n        },\n\t\t{\n\t\t\t\"type\": \"retention_policy\",\n\t\t\t\"id\": \"22223\",\n\t\t\t\"policy_name\": \"Very Short Retention\"\n        }\n    ],\n\t\"limit\": 1000\n}\n"
  },
  {
    "path": "test/fixtures/retention-policies/get_retention_policy_assignments_id.json",
    "content": "{\n    \"type\": \"retention_policy_assignment\",\n    \"id\": \"12345\",\n    \"retention_policy\": {\n        \"type\": \"retention_policy\",\n        \"id\": \"11111\",\n        \"policy_name\": \"Retained Financial Records\"\n    },\n    \"assigned_to\": {\n        \"type\": \"folder\",\n        \"id\": \"22222\"\n    },\n    \"filter_fields\": [],\n    \"assigned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"assigned_at\": \"2018-04-25T20:19:16-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/retention-policies/post_retention_policies.json",
    "content": "{\n    \"type\": \"retention_policy\",\n    \"id\": \"11111\",\n    \"policy_name\": \"Financial Records\",\n    \"policy_type\": \"finite\",\n    \"retention_length\": \"365\",\n    \"retention_type\": \"modifiable\",\n    \"disposition_action\": \"remove_retention\",\n    \"can_owner_extend_retention\": false,\n    \"status\": \"active\",\n    \"are_owners_notified\": false,\n    \"custom_notification_recipients\": [],\n    \"assignment_counts\": {\n        \"enterprise\": 0,\n        \"folder\": 0,\n        \"metadata_template\": 0\n    },\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"created_at\": \"2018-04-25T18:29:40-07:00\",\n    \"modified_at\": \"2018-04-25T18:29:40-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/retention-policies/post_retention_policy_assignments.json",
    "content": "{\n    \"type\": \"retention_policy_assignment\",\n    \"id\": \"12345\",\n    \"retention_policy\": {\n        \"type\": \"retention_policy\",\n        \"id\": \"11111\",\n        \"policy_name\": \"Retained Financial Records\"\n    },\n    \"assigned_to\": {\n        \"type\": \"folder\",\n        \"id\": \"22222\"\n    },\n    \"filter_fields\": [],\n    \"assigned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"assigned_at\": \"2018-04-25T20:19:16-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/retention-policies/put_retention_policies_id.json",
    "content": "{\n    \"type\": \"retention_policy\",\n    \"id\": \"11111\",\n    \"policy_name\": \"Retained Financial Records\",\n    \"policy_type\": \"finite\",\n    \"retention_length\": \"365\",\n    \"retention_type\": \"non_modifiable\",\n    \"disposition_action\": \"remove_retention\",\n    \"can_owner_extend_retention\": false,\n    \"status\": \"active\",\n    \"are_owners_notified\": false,\n    \"custom_notification_recipients\": [],\n    \"assignment_counts\": {\n        \"enterprise\": 0,\n        \"folder\": 0,\n        \"metadata_template\": 0\n    },\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"created_at\": \"2018-04-25T18:29:40-07:00\",\n    \"modified_at\": \"2018-04-25T18:29:40-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/search/bulk/bulk_get_search_query_input.csv",
    "content": "scope,type\nenterprise_content,file\nenterprise_content,folder\n"
  },
  {
    "path": "test/fixtures/search/get_search_query_page_1.json",
    "content": "{\n    \"total_count\": 10,\n    \"entries\": [\n        {\n            \"type\": \"file\",\n            \"id\": \"11111\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"111110\",\n                \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n            },\n            \"sequence_id\": \"9\",\n            \"etag\": \"9\",\n            \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n            \"name\": \"test file.txt\",\n            \"description\": \"\",\n            \"size\": 16,\n            \"path_collection\": {\n                \"total_count\": 1,\n                \"entries\": [\n                    {\n                        \"type\": \"folder\",\n                        \"id\": \"0\",\n                        \"sequence_id\": null,\n                        \"etag\": null,\n                        \"name\": \"All Files\"\n                    }\n                ]\n            },\n            \"created_at\": \"2016-12-07T15:53:59-08:00\",\n            \"modified_at\": \"2018-04-24T15:08:58-07:00\",\n            \"trashed_at\": null,\n            \"purged_at\": null,\n            \"content_created_at\": \"2016-12-07T15:53:59-08:00\",\n            \"content_modified_at\": \"2016-12-07T15:59:32-08:00\",\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"modified_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"owned_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"shared_link\": null,\n            \"parent\": {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            },\n            \"item_status\": \"active\"\n        },\n        {\n            \"type\": \"folder\",\n            \"id\": \"22222\",\n            \"sequence_id\": \"1\",\n            \"etag\": \"1\",\n            \"name\": \"Test Folder\",\n            \"created_at\": \"2016-12-07T16:34:50-08:00\",\n            \"modified_at\": \"2016-12-07T16:34:50-08:00\",\n            \"description\": \"\",\n            \"size\": 0,\n            \"path_collection\": {\n                \"total_count\": 1,\n                \"entries\": [\n                    {\n                        \"type\": \"folder\",\n                        \"id\": \"0\",\n                        \"sequence_id\": null,\n                        \"etag\": null,\n                        \"name\": \"All Files\"\n                    }\n                ]\n            },\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"modified_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"trashed_at\": null,\n            \"purged_at\": null,\n            \"content_created_at\": \"2016-12-07T16:34:50-08:00\",\n            \"content_modified_at\": \"2016-12-07T16:34:50-08:00\",\n            \"owned_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"shared_link\": null,\n            \"folder_upload_email\": null,\n            \"parent\": null,\n            \"item_status\": \"active\"\n        },\n        {\n            \"type\": \"folder\",\n            \"id\": \"33333\",\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"name\": \"SDK Test Folder\",\n            \"created_at\": \"2016-12-07T15:23:44-08:00\",\n            \"modified_at\": \"2016-12-07T15:23:44-08:00\",\n            \"description\": \"\",\n            \"size\": 0,\n            \"path_collection\": {\n                \"total_count\": 1,\n                \"entries\": [\n                    {\n                        \"type\": \"folder\",\n                        \"id\": \"0\",\n                        \"sequence_id\": null,\n                        \"etag\": null,\n                        \"name\": \"All Files\"\n                    }\n                ]\n            },\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"modified_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"trashed_at\": null,\n            \"purged_at\": null,\n            \"content_created_at\": \"2016-12-07T15:23:44-08:00\",\n            \"content_modified_at\": \"2016-12-07T15:23:44-08:00\",\n            \"owned_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"shared_link\": null,\n            \"folder_upload_email\": null,\n            \"parent\": {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            },\n            \"item_status\": \"active\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"44444\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"444440\",\n                \"sha1\": \"12717919be7d81be2a30824d9cf1d0f9aa4465ab\"\n            },\n            \"sequence_id\": \"1\",\n            \"etag\": \"1\",\n            \"sha1\": \"12717919be7d81be2a30824d9cf1d0f9aa4465ab\",\n            \"name\": \"test.js\",\n            \"description\": \"\",\n            \"size\": 362,\n            \"path_collection\": {\n                \"total_count\": 2,\n                \"entries\": [\n                    {\n                        \"type\": \"folder\",\n                        \"id\": \"0\",\n                        \"sequence_id\": null,\n                        \"etag\": null,\n                        \"name\": \"All Files\"\n                    },\n                    {\n                        \"type\": \"folder\",\n                        \"id\": \"12345\",\n                        \"sequence_id\": \"0\",\n                        \"etag\": \"0\",\n                        \"name\": \"Copied Folder\"\n                    }\n                ]\n            },\n            \"created_at\": \"2016-12-08T11:50:43-08:00\",\n            \"modified_at\": \"2016-12-08T14:48:18-08:00\",\n            \"trashed_at\": null,\n            \"purged_at\": null,\n            \"content_created_at\": \"2015-12-17T23:10:11-08:00\",\n            \"content_modified_at\": \"2015-12-17T23:10:11-08:00\",\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"modified_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"owned_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"shared_link\": null,\n            \"parent\": {\n                \"type\": \"folder\",\n                \"id\": \"12345\",\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"name\": \"Copied Folder\"\n            },\n            \"item_status\": \"active\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"55555\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"555550\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"Copied file.txt\",\n            \"description\": \"\",\n            \"size\": 9,\n            \"path_collection\": {\n                \"total_count\": 1,\n                \"entries\": [\n                    {\n                        \"type\": \"folder\",\n                        \"id\": \"0\",\n                        \"sequence_id\": null,\n                        \"etag\": null,\n                        \"name\": \"All Files\"\n                    }\n                ]\n            },\n            \"created_at\": \"2016-12-07T15:56:54-08:00\",\n            \"modified_at\": \"2016-12-07T15:56:54-08:00\",\n            \"trashed_at\": null,\n            \"purged_at\": null,\n            \"content_created_at\": \"2016-12-07T15:53:59-08:00\",\n            \"content_modified_at\": \"2016-12-07T15:53:59-08:00\",\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"modified_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"owned_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"shared_link\": null,\n            \"parent\": {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            },\n            \"item_status\": \"active\"\n        }\n    ],\n    \"limit\": 5,\n    \"offset\": 0\n}"
  },
  {
    "path": "test/fixtures/search/get_search_query_page_2.json",
    "content": "{\n    \"total_count\": 10,\n    \"entries\": [\n        {\n            \"type\": \"file\",\n            \"id\": \"111112\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"111110\",\n                \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n            },\n            \"sequence_id\": \"9\",\n            \"etag\": \"9\",\n            \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n            \"name\": \"test file.txt\",\n            \"description\": \"\",\n            \"size\": 16,\n            \"path_collection\": {\n                \"total_count\": 1,\n                \"entries\": [\n                    {\n                        \"type\": \"folder\",\n                        \"id\": \"0\",\n                        \"sequence_id\": null,\n                        \"etag\": null,\n                        \"name\": \"All Files\"\n                    }\n                ]\n            },\n            \"created_at\": \"2016-12-07T15:53:59-08:00\",\n            \"modified_at\": \"2018-04-24T15:08:58-07:00\",\n            \"trashed_at\": null,\n            \"purged_at\": null,\n            \"content_created_at\": \"2016-12-07T15:53:59-08:00\",\n            \"content_modified_at\": \"2016-12-07T15:59:32-08:00\",\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"modified_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"owned_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"shared_link\": null,\n            \"parent\": {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            },\n            \"item_status\": \"active\"\n        },\n        {\n            \"type\": \"folder\",\n            \"id\": \"222223\",\n            \"sequence_id\": \"1\",\n            \"etag\": \"1\",\n            \"name\": \"Test Folder\",\n            \"created_at\": \"2016-12-07T16:34:50-08:00\",\n            \"modified_at\": \"2016-12-07T16:34:50-08:00\",\n            \"description\": \"\",\n            \"size\": 0,\n            \"path_collection\": {\n                \"total_count\": 1,\n                \"entries\": [\n                    {\n                        \"type\": \"folder\",\n                        \"id\": \"0\",\n                        \"sequence_id\": null,\n                        \"etag\": null,\n                        \"name\": \"All Files\"\n                    }\n                ]\n            },\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"modified_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"trashed_at\": null,\n            \"purged_at\": null,\n            \"content_created_at\": \"2016-12-07T16:34:50-08:00\",\n            \"content_modified_at\": \"2016-12-07T16:34:50-08:00\",\n            \"owned_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"shared_link\": null,\n            \"folder_upload_email\": null,\n            \"parent\": null,\n            \"item_status\": \"active\"\n        },\n        {\n            \"type\": \"folder\",\n            \"id\": \"333334\",\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"name\": \"SDK Test Folder\",\n            \"created_at\": \"2016-12-07T15:23:44-08:00\",\n            \"modified_at\": \"2016-12-07T15:23:44-08:00\",\n            \"description\": \"\",\n            \"size\": 0,\n            \"path_collection\": {\n                \"total_count\": 1,\n                \"entries\": [\n                    {\n                        \"type\": \"folder\",\n                        \"id\": \"0\",\n                        \"sequence_id\": null,\n                        \"etag\": null,\n                        \"name\": \"All Files\"\n                    }\n                ]\n            },\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"modified_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"trashed_at\": null,\n            \"purged_at\": null,\n            \"content_created_at\": \"2016-12-07T15:23:44-08:00\",\n            \"content_modified_at\": \"2016-12-07T15:23:44-08:00\",\n            \"owned_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"shared_link\": null,\n            \"folder_upload_email\": null,\n            \"parent\": {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            },\n            \"item_status\": \"active\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"444445\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"444440\",\n                \"sha1\": \"12717919be7d81be2a30824d9cf1d0f9aa4465ab\"\n            },\n            \"sequence_id\": \"1\",\n            \"etag\": \"1\",\n            \"sha1\": \"12717919be7d81be2a30824d9cf1d0f9aa4465ab\",\n            \"name\": \"test.js\",\n            \"description\": \"\",\n            \"size\": 362,\n            \"path_collection\": {\n                \"total_count\": 2,\n                \"entries\": [\n                    {\n                        \"type\": \"folder\",\n                        \"id\": \"0\",\n                        \"sequence_id\": null,\n                        \"etag\": null,\n                        \"name\": \"All Files\"\n                    },\n                    {\n                        \"type\": \"folder\",\n                        \"id\": \"12345\",\n                        \"sequence_id\": \"0\",\n                        \"etag\": \"0\",\n                        \"name\": \"Copied Folder\"\n                    }\n                ]\n            },\n            \"created_at\": \"2016-12-08T11:50:43-08:00\",\n            \"modified_at\": \"2016-12-08T14:48:18-08:00\",\n            \"trashed_at\": null,\n            \"purged_at\": null,\n            \"content_created_at\": \"2015-12-17T23:10:11-08:00\",\n            \"content_modified_at\": \"2015-12-17T23:10:11-08:00\",\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"modified_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"owned_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"shared_link\": null,\n            \"parent\": {\n                \"type\": \"folder\",\n                \"id\": \"12345\",\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"name\": \"Copied Folder\"\n            },\n            \"item_status\": \"active\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"555556\",\n            \"file_version\": {\n                \"type\": \"file_version\",\n                \"id\": \"555550\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n            },\n            \"sequence_id\": \"0\",\n            \"etag\": \"0\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n            \"name\": \"Copied file.txt\",\n            \"description\": \"\",\n            \"size\": 9,\n            \"path_collection\": {\n                \"total_count\": 1,\n                \"entries\": [\n                    {\n                        \"type\": \"folder\",\n                        \"id\": \"0\",\n                        \"sequence_id\": null,\n                        \"etag\": null,\n                        \"name\": \"All Files\"\n                    }\n                ]\n            },\n            \"created_at\": \"2016-12-07T15:56:54-08:00\",\n            \"modified_at\": \"2016-12-07T15:56:54-08:00\",\n            \"trashed_at\": null,\n            \"purged_at\": null,\n            \"content_created_at\": \"2016-12-07T15:53:59-08:00\",\n            \"content_modified_at\": \"2016-12-07T15:53:59-08:00\",\n            \"created_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"modified_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"owned_by\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            },\n            \"shared_link\": null,\n            \"parent\": {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            },\n            \"item_status\": \"active\"\n        }\n    ],\n    \"limit\": 5,\n    \"offset\": 5\n}"
  },
  {
    "path": "test/fixtures/shared-links/get_folders_id.json",
    "content": "{\n    \"type\": \"folder\",\n    \"id\": \"0\",\n    \"sequence_id\": null,\n    \"etag\": null,\n    \"name\": \"All Files\",\n    \"created_at\": null,\n    \"modified_at\": null,\n    \"description\": \"\",\n    \"size\": 8183737,\n    \"path_collection\": {\n        \"total_count\": 0,\n        \"entries\": []\n    },\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"\",\n        \"name\": \"\",\n        \"login\": \"\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": null,\n    \"content_modified_at\": null,\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"shared_link\": null,\n    \"folder_upload_email\": null,\n    \"parent\": null,\n    \"item_status\": \"active\",\n    \"item_collection\": {\n        \"total_count\": 6,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"44444\",\n                \"sequence_id\": \"1\",\n                \"etag\": \"1\",\n                \"name\": \"Collab Folder\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"55555\",\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"name\": \"Copied Folder\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"66666\",\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"name\": \"SDK Test Folder\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"77777\",\n                \"sequence_id\": \"1\",\n                \"etag\": \"1\",\n                \"name\": \"Test Folder\"\n            },\n            {\n                \"type\": \"file\",\n                \"id\": \"88888\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"888880\",\n                    \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n                },\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n                \"name\": \"Copied file.txt\"\n            },\n            {\n                \"type\": \"file\",\n                \"id\": \"99999\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"999990\",\n                    \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n                },\n                \"sequence_id\": \"9\",\n                \"etag\": \"9\",\n                \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n                \"name\": \"test file.txt\"\n            }\n        ],\n        \"offset\": 0,\n        \"limit\": 100,\n        \"order\": [\n            {\n                \"by\": \"type\",\n                \"direction\": \"ASC\"\n            },\n            {\n                \"by\": \"name\",\n                \"direction\": \"ASC\"\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": "test/fixtures/shared-links/get_shared_items.json",
    "content": "{\n    \"type\": \"file\",\n    \"id\": \"11111\",\n    \"file_version\": {\n        \"type\": \"file_version\",\n        \"id\": \"111110\",\n        \"sha1\": \"de37fa51bfc28ad1cbbd5ca4edb895e57651b2fc\"\n    },\n    \"sequence_id\": \"1\",\n    \"etag\": \"1\",\n    \"sha1\": \"de37fa51bfc28ad1cbbd5ca4edb895e57651b2fc\",\n    \"name\": \"Spreadsheet.csv\",\n    \"description\": \"\",\n    \"size\": 343,\n    \"path_collection\": {\n        \"total_count\": 0,\n        \"entries\": []\n    },\n    \"created_at\": \"2016-09-19T11:16:59-07:00\",\n    \"modified_at\": \"2016-09-19T11:16:59-07:00\",\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": \"2016-09-19T11:16:59-07:00\",\n    \"content_modified_at\": \"2016-09-19T11:16:59-07:00\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"shared_link\": null,\n    \"parent\": null,\n    \"item_status\": \"active\"\n}\n"
  },
  {
    "path": "test/fixtures/shared-links/put_folders_id_shared_link.json",
    "content": "{\n    \"type\": \"folder\",\n    \"id\": \"0\",\n    \"sequence_id\": null,\n    \"etag\": null,\n    \"name\": \"All Files\",\n    \"created_at\": null,\n    \"modified_at\": null,\n    \"description\": \"\",\n    \"size\": 8183737,\n    \"path_collection\": {\n        \"total_count\": 0,\n        \"entries\": []\n    },\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"\",\n        \"name\": \"\",\n        \"login\": \"\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": null,\n    \"content_modified_at\": null,\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"shared_link\": {\n        \"url\": \"https://blosserdemoaccount.box.com/s/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p\",\n        \"download_url\": \"https://blosserdemoaccount.box.com/shared/static/7mcmdlavtye5o5i0ue8xmtwh2sx5bv8p.png\",\n        \"vanity_url\": null,\n        \"effective_access\": \"open\",\n        \"is_password_enabled\": true,\n        \"unshared_at\": null,\n        \"download_count\": 0,\n        \"preview_count\": 0,\n        \"access\": \"test\",\n        \"permissions\": {\n            \"can_download\": true,\n            \"can_preview\": true\n        }\n    },\n    \"folder_upload_email\": null,\n    \"parent\": null,\n    \"item_status\": \"active\",\n    \"item_collection\": {\n        \"total_count\": 6,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"44444\",\n                \"sequence_id\": \"1\",\n                \"etag\": \"1\",\n                \"name\": \"Collab Folder\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"55555\",\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"name\": \"Copied Folder\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"66666\",\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"name\": \"SDK Test Folder\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"77777\",\n                \"sequence_id\": \"1\",\n                \"etag\": \"1\",\n                \"name\": \"Test Folder\"\n            },\n            {\n                \"type\": \"file\",\n                \"id\": \"88888\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"888880\",\n                    \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n                },\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n                \"name\": \"Copied file.txt\"\n            },\n            {\n                \"type\": \"file\",\n                \"id\": \"99999\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"999990\",\n                    \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n                },\n                \"sequence_id\": \"9\",\n                \"etag\": \"9\",\n                \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n                \"name\": \"test file.txt\"\n            }\n        ],\n        \"offset\": 0,\n        \"limit\": 100,\n        \"order\": [\n            {\n                \"by\": \"type\",\n                \"direction\": \"ASC\"\n            },\n            {\n                \"by\": \"name\",\n                \"direction\": \"ASC\"\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": "test/fixtures/sign-requests/get_sign_request_by_id.json",
    "content": "{\n    \"id\": 12345,\n    \"type\": \"sign-request\",\n    \"are_reminders_enabled\": true,\n    \"are_text_signatures_enabled\": true,\n    \"auto_expire_at\": \"2021-04-26T08:12:13.982Z\",\n    \"days_valid\": 2,\n    \"email_message\": \"Hello! Please sign the document below\",\n    \"email_subject\": \"Sign Request from Acme\",\n    \"external_id\": 123,\n    \"is_document_preparation_needed\": true,\n    \"parent_folder\": {\n        \"id\": 12345,\n        \"type\": \"folder\",\n        \"etag\": 1,\n        \"name\": \"Contracts\",\n        \"sequence_id\": 3\n    },\n    \"prefill_tags\": [\n        {\n            \"document_tag_id\": 1234,\n            \"text_value\": \"text\",\n            \"checkbox_value\": true,\n            \"date_value\": \"2021-04-26T08:12:13.982Z\"\n        }\n    ],\n    \"prepare_url\": \"https://prepareurl.com\",\n    \"redirect_url\": \"https://box.com/redirect_url\",\n    \"declined_redirect_url\": \"https://box.com/declined_redirect_url\",\n    \"sign_files\": {\n        \"files\": [\n            {\n                \"id\": 12345,\n                \"etag\": 1,\n                \"type\": \"file\",\n                \"sequence_id\": 3,\n                \"name\": \"Contract.pdf\",\n                \"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\",\n                \"file_version\": {\n                    \"id\": 12345,\n                    \"type\": \"file_version\",\n                    \"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n                }\n            }\n        ],\n        \"is_ready_for_download\": true\n    },\n    \"signers\": [\n        {\n            \"email\": \"example@gmail.com\",\n            \"role\": \"signer\",\n            \"is_in_person\": true,\n            \"order\": 2,\n            \"embed_url_external_user_id\": 1234,\n            \"has_viewed_document\": true,\n            \"signer_decision\": {\n                \"type\": \"signed\",\n                \"finalized_at\": \"2021-04-26T08:12:13.982Z\"\n            },\n            \"inputs\": [\n                {\n                    \"document_tag_id\": 1234,\n                    \"text_value\": \"text\",\n                    \"checkbox_value\": true,\n                    \"date_value\": \"2021-04-26T08:12:13.982Z\",\n                    \"type\": \"text\",\n                    \"page_index\": 4\n                }\n            ],\n            \"embed_url\": \"https://example.com\",\n            \"redirect_url\": \"https://box.com/redirect_url_signer_1\",\n            \"declined_redirect_url\": \"https://box.com/declined_redirect_url_signer_1\",\n            \"iframeable_embed_url\": \"https://app.box.com/embed/sign/document/bf7aaac6-0e77-47da-a86d-92aed1a8c043/bd13d452ea08c9e9e16ef01ecba52b14d337251593c82b850093c1563ee6cfd1/\"\n        }\n    ],\n    \"signing_log\": {\n        \"id\": 12345,\n        \"type\": \"file\",\n        \"etag\": 1,\n        \"file_version\": {\n            \"id\": 12345,\n            \"type\": \"file_version\",\n            \"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n        },\n        \"name\": \"Contract.pdf\",\n        \"sequence_id\": 3,\n        \"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\"\n    },\n    \"source_files\": [\n        {\n            \"id\": 12345,\n            \"etag\": 1,\n            \"type\": \"file\",\n            \"sequence_id\": 3,\n            \"name\": \"Contract.pdf\",\n            \"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\",\n            \"file_version\": {\n                \"id\": 12345,\n                \"type\": \"file_version\",\n                \"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n            }\n        }\n    ],\n    \"status\": \"converting\"\n}\n"
  },
  {
    "path": "test/fixtures/sign-requests/get_sign_requests.json",
    "content": "{\n    \"id\": 12345,\n    \"type\": \"sign-request\",\n    \"are_reminders_enabled\": true,\n    \"are_text_signatures_enabled\": true,\n    \"auto_expire_at\": \"2021-04-26T08:12:13.982Z\",\n    \"days_valid\": 2,\n    \"email_message\": \"Hello! Please sign the document below\",\n    \"email_subject\": \"Sign Request from Acme\",\n    \"external_id\": 123,\n    \"is_document_preparation_needed\": true,\n    \"parent_folder\": {\n        \"id\": 12345,\n        \"type\": \"folder\",\n        \"etag\": 1,\n        \"name\": \"Contracts\",\n        \"sequence_id\": 3\n    },\n    \"prefill_tags\": [\n        {\n            \"document_tag_id\": 1234,\n            \"text_value\": \"text\",\n            \"checkbox_value\": true,\n            \"date_value\": \"2021-04-26T08:12:13.982Z\"\n        }\n    ],\n    \"prepare_url\": \"https://prepareurl.com\",\n    \"redirect_url\": \"https://box.com/redirect_url\",\n    \"declined_redirect_url\": \"https://box.com/declined_redirect_url\",\n    \"sign_files\": {\n        \"files\": [\n            {\n                \"id\": 12345,\n                \"etag\": 1,\n                \"type\": \"file\",\n                \"sequence_id\": 3,\n                \"name\": \"Contract.pdf\",\n                \"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\",\n                \"file_version\": {\n                    \"id\": 12345,\n                    \"type\": \"file_version\",\n                    \"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n                }\n            }\n        ],\n        \"is_ready_for_download\": true\n    },\n    \"signers\": [\n        {\n            \"email\": \"example@gmail.com\",\n            \"role\": \"signer\",\n            \"is_in_person\": true,\n            \"order\": 2,\n            \"embed_url_external_user_id\": 1234,\n            \"has_viewed_document\": true,\n            \"signer_decision\": {\n                \"type\": \"signed\",\n                \"finalized_at\": \"2021-04-26T08:12:13.982Z\"\n            },\n            \"inputs\": [\n                {\n                    \"document_tag_id\": 1234,\n                    \"text_value\": \"text\",\n                    \"checkbox_value\": true,\n                    \"date_value\": \"2021-04-26T08:12:13.982Z\",\n                    \"type\": \"text\",\n                    \"page_index\": 4\n                }\n            ],\n            \"embed_url\": \"https://example.com\",\n            \"redirect_url\": \"https://box.com/redirect_url_signer_1\",\n            \"declined_redirect_url\": \"https://box.com/declined_redirect_url_signer_1\",\n            \"iframeable_embed_url\": \"https://app.box.com/embed/sign/document/bf7aaac6-0e77-47da-a86d-92aed1a8c043/bd13d452ea08c9e9e16ef01ecba52b14d337251593c82b850093c1563ee6cfd1/\"\n        }\n    ],\n    \"signing_log\": {\n        \"id\": 12345,\n        \"type\": \"file\",\n        \"etag\": 1,\n        \"file_version\": {\n            \"id\": 12345,\n            \"type\": \"file_version\",\n            \"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n        },\n        \"name\": \"Contract.pdf\",\n        \"sequence_id\": 3,\n        \"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\"\n    },\n    \"source_files\": [\n        {\n            \"id\": 12345,\n            \"etag\": 1,\n            \"type\": \"file\",\n            \"sequence_id\": 3,\n            \"name\": \"Contract.pdf\",\n            \"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\",\n            \"file_version\": {\n                \"id\": 12345,\n                \"type\": \"file_version\",\n                \"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n            }\n        }\n    ],\n    \"status\": \"converting\"\n}\n"
  },
  {
    "path": "test/fixtures/sign-requests/post_sign_requests.json",
    "content": "{\n    \"id\": 12345,\n    \"type\": \"sign-request\",\n    \"are_reminders_enabled\": true,\n    \"are_text_signatures_enabled\": true,\n    \"auto_expire_at\": \"2021-04-26T08:12:13.982Z\",\n    \"days_valid\": 2,\n    \"email_message\": \"Hello! Please sign the document below\",\n    \"email_subject\": \"Sign Request from Acme\",\n    \"external_id\": 123,\n    \"is_document_preparation_needed\": true,\n    \"parent_folder\": {\n        \"id\": 12345,\n        \"type\": \"folder\",\n        \"etag\": 1,\n        \"name\": \"Contracts\",\n        \"sequence_id\": 3\n    },\n    \"prefill_tags\": [\n        {\n            \"document_tag_id\": 1234,\n            \"text_value\": \"text\",\n            \"checkbox_value\": true,\n            \"date_value\": \"2021-04-26T08:12:13.982Z\"\n        }\n    ],\n    \"prepare_url\": \"https://prepareurl.com\",\n    \"redirect_url\": \"https://box.com/redirect_url\",\n    \"declined_redirect_url\": \"https://box.com/declined_redirect_url\",\n    \"sign_files\": {\n        \"files\": [\n            {\n                \"id\": 12345,\n                \"etag\": 1,\n                \"type\": \"file\",\n                \"sequence_id\": 3,\n                \"name\": \"Contract.pdf\",\n                \"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\",\n                \"file_version\": {\n                    \"id\": 12345,\n                    \"type\": \"file_version\",\n                    \"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n                }\n            }\n        ],\n        \"is_ready_for_download\": true\n    },\n    \"signers\": [\n        {\n            \"email\": \"example@gmail.com\",\n            \"role\": \"signer\",\n            \"is_in_person\": true,\n            \"order\": 2,\n            \"embed_url_external_user_id\": 1234,\n            \"has_viewed_document\": true,\n            \"signer_decision\": {\n                \"type\": \"signed\",\n                \"finalized_at\": \"2021-04-26T08:12:13.982Z\"\n            },\n            \"inputs\": [\n                {\n                    \"document_tag_id\": 1234,\n                    \"text_value\": \"text\",\n                    \"checkbox_value\": true,\n                    \"date_value\": \"2021-04-26T08:12:13.982Z\",\n                    \"type\": \"text\",\n                    \"page_index\": 4\n                }\n            ],\n            \"embed_url\": \"https://example.com\",\n            \"redirect_url\": \"https://box.com/redirect_url_signer_1\",\n            \"declined_redirect_url\": \"https://box.com/declined_redirect_url_signer_1\",\n            \"iframeable_embed_url\": \"https://app.box.com/embed/sign/document/bf7aaac6-0e77-47da-a86d-92aed1a8c043/bd13d452ea08c9e9e16ef01ecba52b14d337251593c82b850093c1563ee6cfd1/\"\n        }\n    ],\n    \"signing_log\": {\n        \"id\": 12345,\n        \"type\": \"file\",\n        \"etag\": 1,\n        \"file_version\": {\n            \"id\": 12345,\n            \"type\": \"file_version\",\n            \"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n        },\n        \"name\": \"Contract.pdf\",\n        \"sequence_id\": 3,\n        \"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\"\n    },\n    \"source_files\": [\n        {\n            \"id\": 12345,\n            \"etag\": 1,\n            \"type\": \"file\",\n            \"sequence_id\": 3,\n            \"name\": \"Contract.pdf\",\n            \"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\",\n            \"file_version\": {\n                \"id\": 12345,\n                \"type\": \"file_version\",\n                \"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n            }\n        }\n    ],\n    \"status\": \"converting\"\n}\n"
  },
  {
    "path": "test/fixtures/sign-requests/post_sign_requests_id_cancel.json",
    "content": "{\n    \"id\": 12345,\n    \"type\": \"sign-request\",\n    \"are_reminders_enabled\": true,\n    \"are_text_signatures_enabled\": true,\n    \"auto_expire_at\": \"2021-04-26T08:12:13.982Z\",\n    \"days_valid\": 2,\n    \"email_message\": \"Hello! Please sign the document below\",\n    \"email_subject\": \"Sign Request from Acme\",\n    \"external_id\": 123,\n    \"is_document_preparation_needed\": true,\n    \"parent_folder\": {\n        \"id\": 12345,\n        \"type\": \"folder\",\n        \"etag\": 1,\n        \"name\": \"Contracts\",\n        \"sequence_id\": 3\n    },\n    \"prefill_tags\": [\n        {\n            \"document_tag_id\": 1234,\n            \"text_value\": \"text\",\n            \"checkbox_value\": true,\n            \"date_value\": \"2021-04-26T08:12:13.982Z\"\n        }\n    ],\n    \"prepare_url\": \"https://prepareurl.com\",\n    \"redirect_url\": \"https://box.com/redirect_url\",\n    \"declined_redirect_url\": \"https://box.com/declined_redirect_url\",\n    \"sign_files\": {\n        \"files\": [\n            {\n                \"id\": 12345,\n                \"etag\": 1,\n                \"type\": \"file\",\n                \"sequence_id\": 3,\n                \"name\": \"Contract.pdf\",\n                \"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\",\n                \"file_version\": {\n                    \"id\": 12345,\n                    \"type\": \"file_version\",\n                    \"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n                }\n            }\n        ],\n        \"is_ready_for_download\": true\n    },\n    \"signers\": [\n        {\n            \"email\": \"example@gmail.com\",\n            \"role\": \"signer\",\n            \"is_in_person\": true,\n            \"order\": 2,\n            \"embed_url_external_user_id\": 1234,\n            \"has_viewed_document\": true,\n            \"signer_decision\": {\n                \"type\": \"signed\",\n                \"finalized_at\": \"2021-04-26T08:12:13.982Z\"\n            },\n            \"inputs\": [\n                {\n                    \"document_tag_id\": 1234,\n                    \"text_value\": \"text\",\n                    \"checkbox_value\": true,\n                    \"date_value\": \"2021-04-26T08:12:13.982Z\",\n                    \"type\": \"text\",\n                    \"page_index\": 4\n                }\n            ],\n            \"embed_url\": \"https://example.com\",\n            \"redirect_url\": \"https://box.com/redirect_url_signer_1\",\n            \"declined_redirect_url\": \"https://box.com/declined_redirect_url_signer_1\",\n            \"iframeable_embed_url\": \"https://app.box.com/embed/sign/document/bf7aaac6-0e77-47da-a86d-92aed1a8c043/bd13d452ea08c9e9e16ef01ecba52b14d337251593c82b850093c1563ee6cfd1/\"\n        }\n    ],\n    \"signing_log\": {\n        \"id\": 12345,\n        \"type\": \"file\",\n        \"etag\": 1,\n        \"file_version\": {\n            \"id\": 12345,\n            \"type\": \"file_version\",\n            \"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n        },\n        \"name\": \"Contract.pdf\",\n        \"sequence_id\": 3,\n        \"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\"\n    },\n    \"source_files\": [\n        {\n            \"id\": 12345,\n            \"etag\": 1,\n            \"type\": \"file\",\n            \"sequence_id\": 3,\n            \"name\": \"Contract.pdf\",\n            \"sha1\": \"85136C79CBF9FE36BB9D05D0639C70C265C18D37\",\n            \"file_version\": {\n                \"id\": 12345,\n                \"type\": \"file_version\",\n                \"sha1\": \"134b65991ed521fcfe4724b7d814ab8ded5185dc\"\n            }\n        }\n    ],\n    \"status\": \"converting\"\n}\n"
  },
  {
    "path": "test/fixtures/sign-templates/get_sign_template_by_id.json",
    "content": "{\n    \"id\": \"93153068-5420-467b-b8ef-aaaaaaaaaaa\",\n    \"name\": \"contract.pdf\",\n    \"email_message\": \"Please sign this document.\\n\\nKind regards,\\n\\nSomeone\",\n    \"email_subject\": \"Someone has requested your signature on a document\",\n    \"parent_folder\": {\n        \"id\": \"1234567890\",\n        \"etag\": \"0\",\n        \"type\": \"folder\",\n        \"sequence_id\": \"0\",\n        \"name\": \"My Sign Requests\"\n    },\n    \"auto_expire_days\": null,\n    \"source_files\": [\n        {\n            \"id\": \"1234567890\",\n            \"etag\": \"0\",\n            \"type\": \"file\",\n            \"sequence_id\": \"0\",\n            \"sha1\": \"082c9540e82e9c465309367a32404054b13aaaaaa\",\n            \"file_version\": {\n                \"id\": \"1234567890\",\n                \"type\": \"file_version\",\n                \"sha1\": \"082c9540e82e9c465309367a32404054b13aaaaaa\"\n            }\n        }\n    ],\n    \"are_email_settings_locked\": false,\n    \"are_fields_locked\": false,\n    \"are_files_locked\": false,\n    \"are_options_locked\": false,\n    \"are_recipients_locked\": false,\n    \"signers\": [\n        {\n            \"email\": \"\",\n            \"label\": \"\",\n            \"public_id\": \"18K8KAAA\",\n            \"role\": \"final_copy_reader\",\n            \"is_in_person\": false,\n            \"order\": 1,\n            \"inputs\": []\n        },\n        {\n            \"email\": \"\",\n            \"label\": \"\",\n            \"public_id\": \"13XQXAAA\",\n            \"role\": \"signer\",\n            \"is_in_person\": false,\n            \"order\": 1,\n            \"inputs\": [\n                {\n                    \"document_tag_id\": null,\n                    \"id\": \"0260f921-3b52-477f-ae74-aaaaaaaaaaa\",\n                    \"type\": \"signature\",\n                    \"text_value\": null,\n                    \"is_required\": true,\n                    \"coordinates\": {\n                        \"x\": 0.27038464059712,\n                        \"y\": 0.10051756244533624\n                    },\n                    \"dimensions\": {\n                        \"width\": 0.23570031566618235,\n                        \"height\": 0.04781003891921971\n                    },\n                    \"date_value\": null,\n                    \"page_index\": 0,\n                    \"checkbox_value\": null,\n                    \"document_id\": \"2fdf9003-d798-40ee-be7f-aaaaaaaaaaa\",\n                    \"content_type\": \"signature\",\n                    \"dropdown_choices\": null,\n                    \"group_id\": null,\n                    \"label\": null\n                }\n            ]\n        }\n    ],\n    \"ready_sign_link\": {\n        \"url\": \"https://app.box.com/sign/ready-sign-link/59917816-c12b-4ef6-8f1d-aaaaaaaaaaa\",\n        \"name\": \"contract.pdf\",\n        \"instructions\": \"Hello\",\n        \"folder_id\": \"1234567890\",\n        \"is_notification_disabled\": true,\n        \"is_active\": true\n    },\n    \"custom_branding\": null,\n    \"days_valid\": 0,\n    \"additional_info\": {\n        \"non_editable\": [],\n        \"required\": {\n            \"signers\": [\n                [\n                    \"email\"\n                ],\n                [\n                    \"email\"\n                ]\n            ]\n        }\n    }\n}\n"
  },
  {
    "path": "test/fixtures/sign-templates/get_sign_templates.json",
    "content": "{\n\t\"limit\": 10,\n\t\"next_marker\": null,\n\t\"prev_marker\": null,\n\t\"entries\": [\n\t\t{\n\t\t\t\"id\": \"93153068-5420-467b-b8ef-aaaaaaaaaaa\",\n\t\t\t\"name\": \"contract.pdf\",\n\t\t\t\"email_message\": \"Please sign this document.\\n\\nKind regards,\\n\\nSomeone\",\n\t\t\t\"email_subject\": \"Someone has requested your signature on a document\",\n\t\t\t\"parent_folder\": {\n\t\t\t\t\"id\": \"1234567890\",\n\t\t\t\t\"etag\": \"0\",\n\t\t\t\t\"type\": \"folder\",\n\t\t\t\t\"sequence_id\": \"0\",\n\t\t\t\t\"name\": \"My Sign Requests\"\n\t\t\t},\n\t\t\t\"auto_expire_days\": null,\n\t\t\t\"source_files\": [\n\t\t\t\t{\n\t\t\t\t\t\"id\": \"1234567890\",\n\t\t\t\t\t\"etag\": \"0\",\n\t\t\t\t\t\"type\": \"file\",\n\t\t\t\t\t\"sequence_id\": \"0\",\n\t\t\t\t\t\"sha1\": \"082c9540e82e9c465309367a32404054b13aaaaaa\",\n\t\t\t\t\t\"file_version\": {\n\t\t\t\t\t\t\"id\": \"1234567890\",\n\t\t\t\t\t\t\"type\": \"file_version\",\n\t\t\t\t\t\t\"sha1\": \"082c9540e82e9c465309367a32404054b13aaaaaa\"\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"are_email_settings_locked\": false,\n\t\t\t\"are_fields_locked\": false,\n\t\t\t\"are_files_locked\": false,\n\t\t\t\"are_options_locked\": false,\n\t\t\t\"are_recipients_locked\": false,\n\t\t\t\"signers\": [\n\t\t\t\t{\n\t\t\t\t\t\"email\": \"\",\n\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\"public_id\": \"18K8KAAA\",\n\t\t\t\t\t\"role\": \"final_copy_reader\",\n\t\t\t\t\t\"is_in_person\": false,\n\t\t\t\t\t\"order\": 1,\n\t\t\t\t\t\"inputs\": []\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"email\": \"\",\n\t\t\t\t\t\"label\": \"\",\n\t\t\t\t\t\"public_id\": \"13XQXAAA\",\n\t\t\t\t\t\"role\": \"signer\",\n\t\t\t\t\t\"is_in_person\": false,\n\t\t\t\t\t\"order\": 1,\n\t\t\t\t\t\"inputs\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"document_tag_id\": null,\n\t\t\t\t\t\t\t\"id\": \"0260f921-3b52-477f-ae74-aaaaaaaaaaa\",\n\t\t\t\t\t\t\t\"type\": \"signature\",\n\t\t\t\t\t\t\t\"text_value\": null,\n\t\t\t\t\t\t\t\"is_required\": true,\n\t\t\t\t\t\t\t\"coordinates\": {\n\t\t\t\t\t\t\t\t\"x\": 0.27038464059712,\n\t\t\t\t\t\t\t\t\"y\": 0.10051756244533624\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"dimensions\": {\n\t\t\t\t\t\t\t\t\"width\": 0.23570031566618235,\n\t\t\t\t\t\t\t\t\"height\": 0.04781003891921971\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\"date_value\": null,\n\t\t\t\t\t\t\t\"page_index\": 0,\n\t\t\t\t\t\t\t\"checkbox_value\": null,\n\t\t\t\t\t\t\t\"document_id\": \"2fdf9003-d798-40ee-be7f-aaaaaaaaaaa\",\n\t\t\t\t\t\t\t\"content_type\": \"signature\",\n\t\t\t\t\t\t\t\"dropdown_choices\": null,\n\t\t\t\t\t\t\t\"group_id\": null,\n\t\t\t\t\t\t\t\"label\": null\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t],\n\t\t\t\"ready_sign_link\": {\n\t\t\t\t\"url\": \"https://app.box.com/sign/ready-sign-link/59917816-c12b-4ef6-8f1d-aaaaaaaaaaa\",\n\t\t\t\t\"name\": \"contract.pdf\",\n\t\t\t\t\"instructions\": \"Hello\",\n\t\t\t\t\"folder_id\": \"1234567890\",\n\t\t\t\t\"is_notification_disabled\": true,\n\t\t\t\t\"is_active\": true\n\t\t\t},\n\t\t\t\"custom_branding\": null,\n\t\t\t\"days_valid\": 0,\n\t\t\t\"additional_info\": {\n\t\t\t\t\"non_editable\": [],\n\t\t\t\t\"required\": {\n\t\t\t\t\t\"signers\": [[\"email\"], [\"email\"]]\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t]\n}\n"
  },
  {
    "path": "test/fixtures/storage-policies/get_storage_policies_id.json",
    "content": "{\n    \"type\": \"storage_policy\",\n    \"id\": \"123\",\n    \"name\": \"AWS\"\n}\n"
  },
  {
    "path": "test/fixtures/storage-policies/get_storage_policies_page_1.json",
    "content": "{\n    \"next_marker\": \"ZDE789\",\n    \"limit\": 1000,\n    \"entries\": [\n        {\n            \"type\": \"storage_policy\",\n            \"id\": \"456\",\n            \"name\": \"Azure\"\n        },\n        {\n            \"type\": \"storage_policy\",\n            \"id\": \"123\",\n            \"name\": \"AWS\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/storage-policies/get_storage_policies_page_2.json",
    "content": "{\n    \"next_marker\": null,\n    \"limit\": 1000,\n    \"entries\": [\n        {\n            \"type\": \"storage_policy\",\n            \"id\": \"456\",\n            \"name\": \"Azure\"\n        },\n        {\n            \"type\": \"storage_policy\",\n            \"id\": \"123\",\n            \"name\": \"AWS\"\n        }\n    ]\n}"
  },
  {
    "path": "test/fixtures/storage-policies/get_storage_policy_assignments_id.json",
    "content": "{\n    \"type\": \"storage_policy_assignment\",\n    \"id\": \"user_987654321\",\n    \"storage_policy\": {\n        \"type\": \"storage_policy\",\n        \"id\": \"123\"\n    },\n    \"assigned_to\": {\n        \"type\": \"user\",\n        \"id\": \"987654321\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/storage-policies/get_storage_policy_assignments_resolved_for_enterprise.json",
    "content": "{\n    \"next_marker\": \"\",\n    \"limit\": 1,\n    \"entries\": [\n        {\n            \"type\": \"storage_policy_assignment\",\n            \"id\": \"enterprise_77777\",\n            \"storage_policy\": {\n                \"type\": \"storage_policy\",\n                \"id\": \"123\"\n            },\n            \"assigned_to\": {\n                \"type\": \"enterprise\",\n                \"id\": \"77777\"\n            }\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/storage-policies/post_storage_policy_assignments.json",
    "content": "{\n    \"type\": \"storage_policy_assignment\",\n    \"id\": \"user_987654321\",\n    \"storage_policy\": {\n        \"type\": \"storage_policy\",\n        \"id\": \"123\"\n    },\n    \"assigned_to\": {\n        \"type\": \"user\",\n        \"id\": \"987654321\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/storage-policies/put_storage_policy_assignments_id.json",
    "content": "{\n    \"type\": \"storage_policy_assignment\",\n    \"id\": \"user_987654321\",\n    \"storage_policy\": {\n        \"type\": \"storage_policy\",\n        \"id\": \"456\"\n    },\n    \"assigned_to\": {\n        \"type\": \"user\",\n        \"id\": \"987654321\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/task-assignments/get_tasks_id_assignments.json",
    "content": "{\n    \"total_count\": 1,\n    \"entries\": [\n        {\n            \"type\": \"task_assignment\",\n            \"id\": \"12345\",\n            \"item\": {\n                \"type\": \"file\",\n                \"id\": \"22222\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"222220\",\n                    \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n                },\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n                \"name\": \"Copied file.txt\"\n            },\n            \"assigned_to\": {\n                \"type\": \"user\",\n                \"id\": \"33333\",\n                \"name\": \"Test User\",\n                \"login\": \"testuser@example.com\"\n            }\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/task-assignments/post_task_assignments.json",
    "content": "{\n    \"type\": \"task_assignment\",\n    \"id\": \"12345\",\n    \"item\": {\n        \"type\": \"file\",\n        \"id\": \"22222\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"222220\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n        },\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n        \"name\": \"Copied file.txt\"\n    },\n    \"assigned_to\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"message\": \"\",\n    \"completed_at\": null,\n    \"assigned_at\": \"2018-04-26T19:12:18-07:00\",\n    \"reminded_at\": null,\n    \"resolution_state\": \"incomplete\",\n    \"assigned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/task-assignments/put_task_assignments_id.json",
    "content": "{\n    \"type\": \"task_assignment\",\n    \"id\": \"12345\",\n    \"item\": {\n        \"type\": \"file\",\n        \"id\": \"22222\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"222220\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n        },\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n        \"name\": \"Copied file.txt\"\n    },\n    \"assigned_to\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"message\": \"Looks good to me!\",\n    \"completed_at\": \"2018-04-26T19:26:23-07:00\",\n    \"assigned_at\": \"2018-04-26T19:12:18-07:00\",\n    \"reminded_at\": null,\n    \"resolution_state\": \"completed\",\n    \"assigned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/tasks/get_tasks_id.json",
    "content": "{\n    \"type\": \"task_assignment\",\n    \"id\": \"12345\",\n    \"item\": {\n        \"type\": \"file\",\n        \"id\": \"22222\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"222220\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n        },\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n        \"name\": \"Copied file.txt\"\n    },\n    \"assigned_to\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"message\": \"\",\n    \"completed_at\": null,\n    \"assigned_at\": \"2018-04-26T19:12:18-07:00\",\n    \"reminded_at\": null,\n    \"resolution_state\": \"incomplete\",\n    \"assigned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/tasks/post_tasks.json",
    "content": "{\n    \"type\": \"task\",\n    \"id\": \"11111\",\n    \"item\": {\n        \"type\": \"file\",\n        \"id\": \"22222\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"222220\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n        },\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n        \"name\": \"Copied file.txt\"\n    },\n    \"due_at\": null,\n    \"action\": \"review\",\n    \"message\": \"Please review\",\n    \"task_assignment_collection\": {\n        \"total_count\": 0,\n        \"entries\": []\n    },\n    \"is_completed\": false,\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"created_at\": \"2018-04-26T11:50:45-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/tasks/put_tasks_id.json",
    "content": "{\n    \"type\": \"task\",\n    \"id\": \"11111\",\n    \"item\": {\n        \"type\": \"file\",\n        \"id\": \"22222\",\n        \"file_version\": {\n            \"type\": \"file_version\",\n            \"id\": \"222220\",\n            \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n        },\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n        \"name\": \"Copied file.txt\"\n    },\n    \"due_at\": null,\n    \"action\": \"review\",\n    \"message\": \"Could you please review this?\",\n    \"task_assignment_collection\": {\n        \"total_count\": 0,\n        \"entries\": []\n    },\n    \"is_completed\": false,\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"created_at\": \"2018-04-26T11:50:45-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/terms-of-service/get_collaborations_id_acceptance_requirements.json",
    "content": "{\n    \"type\": \"collaboration\",\n    \"id\": \"1234567890\",\n    \"acceptance_requirements\": {\n        \"terms_of_service\": {\n            \"type\": \"terms_of_service\",\n            \"id\": \"456\"\n        }\n    }\n}\n"
  },
  {
    "path": "test/fixtures/terms-of-service/get_terms_of_service_id.json",
    "content": "{\n    \"type\": \"terms_of_service\",\n    \"id\": \"12345\",\n    \"status\": \"disabled\",\n    \"enterprise\": {\n        \"type\": \"enterprise\",\n        \"id\": \"1111\",\n        \"name\": \"Test\"\n    },\n    \"tos_type\": \"managed\",\n    \"text\": \"\",\n    \"created_at\": \"2015-06-03T18:01:29-07:00\",\n    \"modified_at\": \"2018-04-18T17:44:10-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/terms-of-service/get_terms_of_service_user_statuses.json",
    "content": "{\n    \"total_count\": 1,\n    \"entries\": [\n        {\n            \"type\": \"terms_of_service_user_status\",\n            \"id\": \"5678\",\n            \"tos\": {\n                \"type\": \"terms_of_service\",\n                \"id\": \"1234\"\n            },\n            \"user\": {\n                \"type\": \"user\",\n                \"id\": \"7777\",\n                \"name\": \"Test User\",\n                \"login\": \"test@example.com\"\n            },\n            \"is_accepted\": true,\n            \"created_at\": \"2015-06-03T18:01:31-07:00\",\n            \"modified_at\": \"2017-11-01T13:39:36-07:00\"\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/terms-of-service/get_terms_of_services.json",
    "content": "{\n    \"total_count\": 2,\n    \"entries\": [\n        {\n            \"type\": \"terms_of_service\",\n            \"id\": \"12345\",\n            \"status\": \"disabled\",\n            \"enterprise\": {\n                \"type\": \"enterprise\",\n                \"id\": \"1111\",\n                \"name\": \"Test\"\n            },\n            \"tos_type\": \"managed\",\n            \"text\": \"\",\n            \"created_at\": \"2015-06-03T18:01:29-07:00\",\n            \"modified_at\": \"2018-04-18T17:44:10-07:00\"\n        },\n        {\n            \"type\": \"terms_of_service\",\n            \"id\": \"42343\",\n            \"status\": \"disabled\",\n            \"enterprise\": {\n                \"type\": \"enterprise\",\n                \"id\": \"2222\",\n                \"name\": \"Test\"\n            },\n            \"tos_type\": \"external\",\n            \"text\": \"Example Terms Of Service Text.\",\n            \"created_at\": \"2015-06-03T18:01:29-07:00\",\n            \"modified_at\": \"2017-10-25T11:20:45-07:00\"\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/terms-of-service/post_terms_of_service_id.json",
    "content": "{\n    \"type\": \"terms_of_service\",\n    \"id\": \"12345\",\n    \"status\": \"enabled\",\n    \"enterprise\": {\n        \"type\": \"enterprise\",\n        \"id\": \"1111\",\n        \"name\": \"Test\"\n    },\n    \"tos_type\": \"managed\",\n    \"text\": \"test\",\n    \"created_at\": \"2015-06-03T18:01:29-07:00\",\n    \"modified_at\": \"2018-04-18T17:44:10-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/terms-of-service/post_terms_of_service_user_statuses.json",
    "content": "{\n    \"type\": \"terms_of_service_user_status\",\n    \"id\": \"12345\",\n    \"tos\": {\n        \"type\": \"terms_of_service\",\n        \"id\": \"11111\"\n    },\n    \"user\": {\n        \"type\": \"user\",\n        \"id\": \"22222\"\n    },\n    \"is_accepted\": true,\n    \"created_at\": \"2018-04-11T15:33:49-07:00\",\n    \"modified_at\": \"2018-04-11T15:33:49-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/terms-of-service/post_terms_of_service_user_statuses_409.json",
    "content": "{\n    \"type\": \"error\",\n    \"status\": 409,\n    \"code\": \"conflict\",\n    \"help_url\": \"http://developers.box.com/docs/#errors\",\n    \"message\": \"Terms of Service User status already exists.\",\n    \"request_id\": \"8888\"\n}\n"
  },
  {
    "path": "test/fixtures/terms-of-service/put_terms_of_service_id.json",
    "content": "{\n    \"type\": \"terms_of_service\",\n    \"id\": \"12345\",\n    \"status\": \"enabled\",\n    \"enterprise\": {\n        \"type\": \"enterprise\",\n        \"id\": \"1111\",\n        \"name\": \"Test\"\n    },\n    \"tos_type\": \"managed\",\n    \"text\": \"test\",\n    \"created_at\": \"2015-06-03T18:01:29-07:00\",\n    \"modified_at\": \"2018-04-18T17:44:10-07:00\"\n}\n"
  },
  {
    "path": "test/fixtures/terms-of-service/put_terms_of_service_user_statuses.json",
    "content": "{\n    \"type\": \"terms_of_service_user_status\",\n    \"id\": \"5678\",\n    \"tos\": {\n        \"type\": \"terms_of_service\",\n        \"id\": \"1234\"\n    },\n    \"user\": {\n        \"type\": \"user\",\n        \"id\": \"7777\",\n        \"name\": \"Test User\",\n        \"login\": \"test@example.com\"\n    },\n    \"is_accepted\": true,\n    \"created_at\": \"2015-06-03T18:01:31-07:00\",\n    \"modified_at\": \"2017-11-13T12:49:38-08:00\"\n}\n"
  },
  {
    "path": "test/fixtures/trash/get_files_id_trash.json",
    "content": "{\n    \"type\": \"file\",\n    \"id\": \"12345\",\n    \"file_version\": {\n        \"type\": \"file_version\",\n        \"id\": \"11223344556677\",\n        \"sha1\": \"97b3dbba6eab7ad0f058240744c8636b7c7bea93\"\n    },\n    \"sequence_id\": \"1\",\n    \"etag\": \"1\",\n    \"sha1\": \"97b3dbba6eab7ad0f058240744c8636b7c7bea93\",\n    \"name\": \"test_file_download.txt\",\n    \"description\": \"\",\n    \"size\": 106833,\n    \"path_collection\": {\n        \"total_count\": 2,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            }\n        ]\n    },\n    \"created_at\": \"2016-11-16T22:01:44-08:00\",\n    \"modified_at\": \"2016-11-16T22:01:51-08:00\",\n    \"trashed_at\": \"2012-12-12T10:53:43-08:00\",\n    \"purged_at\": \"2012-12-12T10:53:43-08:00\",\n    \"content_created_at\": \"2016-10-29T18:33:50-07:00\",\n    \"content_modified_at\": \"2016-10-29T18:33:50-07:00\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"shared_link\": null,\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"0\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"All files\"\n    },\n    \"item_status\": \"active\"\n}"
  },
  {
    "path": "test/fixtures/trash/get_folders_id_trash.json",
    "content": "{\n    \"id\": \"12345\",\n    \"etag\": 1,\n    \"type\": \"folder\",\n    \"sequence_id\": 3,\n    \"name\": \"Contracts\",\n    \"created_at\": \"2012-12-12T10:53:43-08:00\",\n    \"modified_at\": \"2012-12-12T10:53:43-08:00\",\n    \"description\": \"Legal contracts for the new ACME deal\",\n    \"size\": 629644,\n    \"path_collection\": {\n        \"total_count\": 1,\n        \"entries\": [\n            {\n                \"id\": \"0\",\n                \"etag\": 1,\n                \"type\": \"folder\",\n                \"sequence_id\": 3,\n                \"name\": \"All files\"\n            }\n        ]\n    },\n    \"created_by\": {\n        \"id\": \"11446498\",\n        \"type\": \"user\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"ceo@example.com\"\n    },\n    \"modified_by\": {\n        \"id\": \"11446498\",\n        \"type\": \"user\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"ceo@example.com\"\n    },\n    \"trashed_at\": \"2012-12-12T10:53:43-08:00\",\n    \"purged_at\": \"2012-12-12T10:53:43-08:00\",\n    \"content_created_at\": \"2012-12-12T10:53:43-08:00\",\n    \"content_modified_at\": \"2012-12-12T10:53:43-08:00\",\n    \"expires_at\": \"2012-12-12T10:53:43-08:00\",\n    \"owned_by\": {\n        \"id\": \"11446498\",\n        \"type\": \"user\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"ceo@example.com\"\n    },\n    \"shared_link\": {\n        \"url\": \"https://www.box.com/s/vspke7y05sb214wjokpk\",\n        \"download_url\": \"https://www.box.com/shared/static/rh935iit6ewrmw0unyul.jpeg\",\n        \"vanity_url\": \"https://acme.app.box.com/v/my_url/\",\n        \"access\": \"open\",\n        \"effective_access\": \"company\",\n        \"effective_permission\": \"can_download\",\n        \"unshared_at\": \"2018-04-13T13:53:23-07:00\",\n        \"is_password_enabled\": true,\n        \"permissions\": {\n            \"can_download\": true,\n            \"can_preview\": true\n        },\n        \"download_count\": 3,\n        \"preview_count\": 3\n    },\n    \"folder_upload_email\": {\n        \"access\": \"open\",\n        \"email\": \"upload.Contracts.asd7asd@u.box.com\"\n    },\n    \"parent\": {\n        \"id\": \"0\",\n        \"etag\": 1,\n        \"type\": \"folder\",\n        \"sequence_id\": 3,\n        \"name\": \"All files\"\n    },\n    \"item_status\": \"active\",\n    \"item_collection\": {\n        \"total_count\": 5000,\n        \"limit\": 1000,\n        \"offset\": 2000,\n        \"order\": [\n            {\n                \"by\": \"type\",\n                \"direction\": \"ASC\"\n            }\n        ],\n        \"entries\": [\n            {\n                \"id\": \"123456\",\n                \"etag\": 1,\n                \"type\": \"file\",\n                \"sequence_id\": 3,\n                \"name\": \"Contract.pdf\"\n            }\n        ]\n    },\n    \"sync_state\": \"synced\",\n    \"has_collaborations\": true,\n    \"permissions\": {\n        \"can_delete\": true,\n        \"can_download\": true,\n        \"can_invite_collaborator\": true,\n        \"can_rename\": true,\n        \"can_set_share_access\": true,\n        \"can_share\": true,\n        \"can_upload\": true\n    },\n    \"tags\": [\n        \"approved\"\n    ],\n    \"can_non_owners_invite\": true,\n    \"is_externally_owned\": true,\n    \"is_collaboration_restricted_to_enterprise\": true,\n    \"allowed_shared_link_access_levels\": [\n        \"open\"\n    ],\n    \"allowed_invitee_roles\": [\n        \"editor\"\n    ],\n    \"watermark_info\": {\n        \"is_watermarked\": true\n    },\n    \"can_non_owners_view_collaborators\": true\n  }"
  },
  {
    "path": "test/fixtures/trash/get_trashed_items_page_1.json",
    "content": "{\n    \"total_count\": 4,\n    \"entries\": [\n        {\n            \"type\": \"file\",\n            \"id\": \"2701979016\",\n            \"sequence_id\": \"1\",\n            \"etag\": \"1\",\n            \"sha1\": \"9d976863fc849f6061ecf9736710bd9c2bce488c\",\n            \"name\": \"file Tue Jul 24 145436 2012KWPX5S.csv\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"2698211586\",\n            \"sequence_id\": \"1\",\n            \"etag\": \"1\",\n            \"sha1\": \"09b0e2e9760caf7448c702db34ea001f356f1197\",\n            \"name\": \"file Tue Jul 24 010055 20129Z6GS3.csv\"\n        }\n    ],\n    \"offset\": 0,\n    \"limit\": 2\n}"
  },
  {
    "path": "test/fixtures/trash/get_trashed_items_page_2.json",
    "content": "{\n    \"total_count\": 4,\n    \"entries\": [\n        {\n            \"type\": \"file\",\n            \"id\": \"2701979019\",\n            \"sequence_id\": \"1\",\n            \"etag\": \"1\",\n            \"sha1\": \"9d976863fc849f6061ecf9736710bd9c2bce488c\",\n            \"name\": \"file Tue Jul 24 145436 2012KWPX5S.csv\"\n        },\n        {\n            \"type\": \"file\",\n            \"id\": \"2698211570\",\n            \"sequence_id\": \"1\",\n            \"etag\": \"1\",\n            \"sha1\": \"09b0e2e9760caf7448c702db34ea001f356f1197\",\n            \"name\": \"file Tue Jul 24 010055 20129Z6GS3.csv\"\n        }\n    ],\n    \"offset\": 2,\n    \"limit\": 2\n}"
  },
  {
    "path": "test/fixtures/trash/get_web_links_id_trash.json",
    "content": "{\n    \"type\": \"web_link\",\n    \"id\": \"12345\",\n    \"sequence_id\": \"4\",\n    \"etag\": \"4\",\n    \"name\": \"Contracts\",\n    \"url\": \"https://www.box.com\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"11446498\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"ceo@example.com\"\n    },\n    \"created_at\": \"2019-12-16T12:14:30-08:00\",\n    \"modified_at\": \"2019-12-16T12:14:30-08:00\",\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"0\",\n        \"sequence_id\": null,\n        \"etag\": null,\n        \"name\": \"All Files\"\n    },\n    \"description\": \"Cloud Content Management\",\n    \"item_status\": \"active\",\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"shared_link\": null,\n    \"path_collection\": {\n        \"total_count\": 1,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            }\n        ]\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"11446498\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"ceo@example.com\"\n    },\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"11446498\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"ceo@example.com\"\n    }\n}"
  },
  {
    "path": "test/fixtures/trash/post_files_id.json",
    "content": "{\n    \"type\": \"file\",\n    \"id\": \"12345\",\n    \"file_version\": {\n        \"type\": \"file_version\",\n        \"id\": \"11223344556677\",\n        \"sha1\": \"97b3dbba6eab7ad0f058240744c8636b7c7bea93\"\n    },\n    \"sequence_id\": \"1\",\n    \"etag\": \"1\",\n    \"sha1\": \"97b3dbba6eab7ad0f058240744c8636b7c7bea93\",\n    \"name\": \"test_file_download.txt\",\n    \"description\": \"\",\n    \"size\": 106833,\n    \"path_collection\": {\n        \"total_count\": 2,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            }\n        ]\n    },\n    \"created_at\": \"2016-11-16T22:01:44-08:00\",\n    \"modified_at\": \"2016-11-16T22:01:51-08:00\",\n    \"trashed_at\": \"2012-12-12T10:53:43-08:00\",\n    \"purged_at\": \"2012-12-12T10:53:43-08:00\",\n    \"content_created_at\": \"2016-10-29T18:33:50-07:00\",\n    \"content_modified_at\": \"2016-10-29T18:33:50-07:00\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"1357924680\",\n        \"name\": \"Owner\",\n        \"login\": \"owner@example.com\"\n    },\n    \"shared_link\": null,\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"0\",\n        \"sequence_id\": \"0\",\n        \"etag\": \"0\",\n        \"name\": \"All files\"\n    },\n    \"item_status\": \"active\"\n}"
  },
  {
    "path": "test/fixtures/trash/post_folders_id.json",
    "content": "{\n  \"id\": \"12345\",\n  \"etag\": 1,\n  \"type\": \"folder\",\n  \"sequence_id\": 3,\n  \"name\": \"Contracts\",\n  \"created_at\": \"2012-12-12T10:53:43-08:00\",\n  \"modified_at\": \"2012-12-12T10:53:43-08:00\",\n  \"description\": \"Legal contracts for the new ACME deal\",\n  \"size\": 629644,\n  \"path_collection\": {\n      \"total_count\": 1,\n      \"entries\": [\n          {\n              \"id\": \"0\",\n              \"etag\": 1,\n              \"type\": \"folder\",\n              \"sequence_id\": 3,\n              \"name\": \"All files\"\n          }\n      ]\n  },\n  \"created_by\": {\n      \"id\": \"11446498\",\n      \"type\": \"user\",\n      \"name\": \"Aaron Levie\",\n      \"login\": \"ceo@example.com\"\n  },\n  \"modified_by\": {\n      \"id\": \"11446498\",\n      \"type\": \"user\",\n      \"name\": \"Aaron Levie\",\n      \"login\": \"ceo@example.com\"\n  },\n  \"trashed_at\": \"2012-12-12T10:53:43-08:00\",\n  \"purged_at\": \"2012-12-12T10:53:43-08:00\",\n  \"content_created_at\": \"2012-12-12T10:53:43-08:00\",\n  \"content_modified_at\": \"2012-12-12T10:53:43-08:00\",\n  \"expires_at\": \"2012-12-12T10:53:43-08:00\",\n  \"owned_by\": {\n      \"id\": \"11446498\",\n      \"type\": \"user\",\n      \"name\": \"Aaron Levie\",\n      \"login\": \"ceo@example.com\"\n  },\n  \"shared_link\": {\n      \"url\": \"https://www.box.com/s/vspke7y05sb214wjokpk\",\n      \"download_url\": \"https://www.box.com/shared/static/rh935iit6ewrmw0unyul.jpeg\",\n      \"vanity_url\": \"https://acme.app.box.com/v/my_url/\",\n      \"access\": \"open\",\n      \"effective_access\": \"company\",\n      \"effective_permission\": \"can_download\",\n      \"unshared_at\": \"2018-04-13T13:53:23-07:00\",\n      \"is_password_enabled\": true,\n      \"permissions\": {\n          \"can_download\": true,\n          \"can_preview\": true\n      },\n      \"download_count\": 3,\n      \"preview_count\": 3\n  },\n  \"folder_upload_email\": {\n      \"access\": \"open\",\n      \"email\": \"upload.Contracts.asd7asd@u.box.com\"\n  },\n  \"parent\": {\n      \"id\": \"0\",\n      \"etag\": 1,\n      \"type\": \"folder\",\n      \"sequence_id\": 3,\n      \"name\": \"All files\"\n  },\n  \"item_status\": \"active\",\n  \"item_collection\": {\n      \"total_count\": 5000,\n      \"limit\": 1000,\n      \"offset\": 2000,\n      \"order\": [\n          {\n              \"by\": \"type\",\n              \"direction\": \"ASC\"\n          }\n      ],\n      \"entries\": [\n          {\n              \"id\": \"123456\",\n              \"etag\": 1,\n              \"type\": \"file\",\n              \"sequence_id\": 3,\n              \"name\": \"Contract.pdf\"\n          }\n      ]\n  },\n  \"sync_state\": \"synced\",\n  \"has_collaborations\": true,\n  \"permissions\": {\n      \"can_delete\": true,\n      \"can_download\": true,\n      \"can_invite_collaborator\": true,\n      \"can_rename\": true,\n      \"can_set_share_access\": true,\n      \"can_share\": true,\n      \"can_upload\": true\n  },\n  \"tags\": [\n      \"approved\"\n  ],\n  \"can_non_owners_invite\": true,\n  \"is_externally_owned\": true,\n  \"is_collaboration_restricted_to_enterprise\": true,\n  \"allowed_shared_link_access_levels\": [\n      \"open\"\n  ],\n  \"allowed_invitee_roles\": [\n      \"editor\"\n  ],\n  \"watermark_info\": {\n      \"is_watermarked\": true\n  },\n  \"can_non_owners_view_collaborators\": true\n}"
  },
  {
    "path": "test/fixtures/trash/post_web_links_id.json",
    "content": "{\n    \"type\": \"web_link\",\n    \"id\": \"12345\",\n    \"sequence_id\": \"4\",\n    \"etag\": \"4\",\n    \"name\": \"Contracts\",\n    \"url\": \"https://www.box.com\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"11446498\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"ceo@example.com\"\n    },\n    \"created_at\": \"2019-12-16T12:14:30-08:00\",\n    \"modified_at\": \"2019-12-16T12:14:30-08:00\",\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"0\",\n        \"sequence_id\": null,\n        \"etag\": null,\n        \"name\": \"All Files\"\n    },\n    \"description\": \"Cloud Content Management\",\n    \"item_status\": \"active\",\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"shared_link\": null,\n    \"path_collection\": {\n        \"total_count\": 1,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            }\n        ]\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"11446498\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"ceo@example.com\"\n    },\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"11446498\",\n        \"name\": \"Aaron Levie\",\n        \"login\": \"ceo@example.com\"\n    }\n}"
  },
  {
    "path": "test/fixtures/users/get_users_id.json",
    "content": "{\n    \"type\": \"user\",\n    \"id\": \"33333\",\n    \"name\": \"Test User\",\n    \"login\": \"testuser@example.com\",\n    \"created_at\": \"2016-11-09T15:57:20-08:00\",\n    \"modified_at\": \"2018-04-25T17:07:47-07:00\",\n    \"language\": \"en\",\n    \"timezone\": \"America/Los_Angeles\",\n    \"space_amount\": 1000000000000000,\n    \"space_used\": 38243356,\n    \"max_upload_size\": 5368709120,\n    \"status\": \"active\",\n    \"job_title\": \"\",\n    \"phone\": \"555-555-5555\",\n    \"address\": \"\",\n    \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n}\n"
  },
  {
    "path": "test/fixtures/users/get_users_id_email_aliases.json",
    "content": "{\n    \"total_count\": 1,\n    \"entries\": [\n        {\n            \"type\": \"email_alias\",\n            \"id\": \"1234\",\n            \"is_confirmed\": true,\n            \"email\": \"dglover2@example.com\"\n        },\n        {\n            \"type\": \"email_alias\",\n            \"id\": \"1235\",\n            \"is_confirmed\": true,\n            \"email\": \"dglover3@example.com\"\n        }\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/users/get_users_id_memberships_page_1.json",
    "content": "{\n    \"total_count\": 2,\n    \"entries\": [\n        {\n            \"type\": \"group_membership\",\n            \"id\": \"1560354\",\n            \"user\": {\n                \"type\": \"user\",\n                \"id\": \"13130406\",\n                \"name\": \"Alison Wonderland\",\n                \"login\": \"alice@gmail.com\"\n            },\n            \"group\": {\n                \"type\": \"group\",\n                \"id\": \"119720\",\n                \"name\": \"family\"\n            },\n            \"role\": \"member\"\n        }\n    ],\n    \"limit\": 1,\n    \"offset\": 0\n}\n"
  },
  {
    "path": "test/fixtures/users/get_users_id_memberships_page_2.json",
    "content": "{\n    \"total_count\": 2,\n    \"entries\": [\n        {\n            \"type\": \"group_membership\",\n            \"id\": \"1560354\",\n            \"user\": {\n                \"type\": \"user\",\n                \"id\": \"13130406\",\n                \"name\": \"Alison Wonderland\",\n                \"login\": \"alice@gmail.com\"\n            },\n            \"group\": {\n                \"type\": \"group\",\n                \"id\": \"119723\",\n                \"name\": \"family\"\n            },\n            \"role\": \"member\"\n        }\n    ],\n    \"limit\": 1,\n    \"offset\": 1\n}\n"
  },
  {
    "path": "test/fixtures/users/get_users_page_1.json",
    "content": "{\n    \"total_count\": 6,\n    \"entries\": [\n        {\n            \"type\": \"user\",\n            \"id\": \"33333\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\",\n            \"created_at\": \"2016-11-09T15:57:20-08:00\",\n            \"modified_at\": \"2018-04-26T19:46:19-07:00\",\n            \"language\": \"en\",\n            \"timezone\": \"America/Los_Angeles\",\n            \"space_amount\": 1000000000000000,\n            \"space_used\": 38243356,\n            \"max_upload_size\": 5368709120,\n            \"status\": \"active\",\n            \"job_title\": \"CEO\",\n            \"phone\": \"(555) 555-5555\",\n            \"address\": \"\",\n            \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n        },\n        {\n            \"type\": \"user\",\n            \"id\": \"44444\",\n            \"name\": \"Test User 2\",\n            \"login\": \"testuser2@example.com\",\n            \"created_at\": \"2016-11-16T21:46:24-08:00\",\n            \"modified_at\": \"2017-12-21T14:12:42-08:00\",\n            \"language\": \"en\",\n            \"timezone\": \"America/Los_Angeles\",\n            \"space_amount\": 1000000000000000,\n            \"space_used\": 0,\n            \"max_upload_size\": 5368709120,\n            \"status\": \"active\",\n            \"job_title\": \"\",\n            \"phone\": \"\",\n            \"address\": \"\",\n            \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n        },\n        {\n            \"type\": \"user\",\n            \"id\": \"55555\",\n            \"name\": \"Test User 3\",\n            \"login\": \"testuser3@example.com\",\n            \"created_at\": \"2016-12-07T16:49:13-08:00\",\n            \"modified_at\": \"2017-12-21T14:12:42-08:00\",\n            \"language\": \"en\",\n            \"timezone\": \"America/Los_Angeles\",\n            \"space_amount\": 1000000000000000,\n            \"space_used\": 790226181,\n            \"max_upload_size\": 5368709120,\n            \"status\": \"active\",\n            \"job_title\": \"\",\n            \"phone\": \"\",\n            \"address\": \"\",\n            \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n        }\n    ],\n    \"limit\": 3,\n    \"offset\": 0\n}\n"
  },
  {
    "path": "test/fixtures/users/get_users_page_2.json",
    "content": "{\n    \"total_count\": 6,\n    \"entries\": [\n        {\n            \"type\": \"user\",\n            \"id\": \"333334\",\n            \"name\": \"Test User\",\n            \"login\": \"testuser@example.com\",\n            \"created_at\": \"2016-11-09T15:57:20-08:00\",\n            \"modified_at\": \"2018-04-26T19:46:19-07:00\",\n            \"language\": \"en\",\n            \"timezone\": \"America/Los_Angeles\",\n            \"space_amount\": 1000000000000000,\n            \"space_used\": 38243356,\n            \"max_upload_size\": 5368709120,\n            \"status\": \"active\",\n            \"job_title\": \"CEO\",\n            \"phone\": \"(555) 555-5555\",\n            \"address\": \"\",\n            \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n        },\n        {\n            \"type\": \"user\",\n            \"id\": \"444445\",\n            \"name\": \"Test User 2\",\n            \"login\": \"testuser2@example.com\",\n            \"created_at\": \"2016-11-16T21:46:24-08:00\",\n            \"modified_at\": \"2017-12-21T14:12:42-08:00\",\n            \"language\": \"en\",\n            \"timezone\": \"America/Los_Angeles\",\n            \"space_amount\": 1000000000000000,\n            \"space_used\": 0,\n            \"max_upload_size\": 5368709120,\n            \"status\": \"active\",\n            \"job_title\": \"\",\n            \"phone\": \"\",\n            \"address\": \"\",\n            \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n        },\n        {\n            \"type\": \"user\",\n            \"id\": \"555556\",\n            \"name\": \"Test User 3\",\n            \"login\": \"testuser3@example.com\",\n            \"created_at\": \"2016-12-07T16:49:13-08:00\",\n            \"modified_at\": \"2017-12-21T14:12:42-08:00\",\n            \"language\": \"en\",\n            \"timezone\": \"America/Los_Angeles\",\n            \"space_amount\": 1000000000000000,\n            \"space_used\": 790226181,\n            \"max_upload_size\": 5368709120,\n            \"status\": \"active\",\n            \"job_title\": \"\",\n            \"phone\": \"\",\n            \"address\": \"\",\n            \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n        }\n    ],\n    \"limit\": 3,\n    \"offset\": 3\n}\n"
  },
  {
    "path": "test/fixtures/users/post_users.json",
    "content": "{\n    \"type\": \"user\",\n    \"id\": \"77777\",\n    \"name\": \"Another Test User\",\n    \"login\": \"anothertestuser@example.com\",\n    \"created_at\": \"2018-04-26T20:19:51-07:00\",\n    \"modified_at\": \"2018-04-26T20:19:52-07:00\",\n    \"language\": \"en\",\n    \"timezone\": \"America/Los_Angeles\",\n    \"space_amount\": 10737418240,\n    \"space_used\": 0,\n    \"max_upload_size\": 5368709120,\n    \"status\": \"active\",\n    \"job_title\": \"\",\n    \"phone\": \"1234567890\",\n    \"address\": \"\",\n    \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n}\n"
  },
  {
    "path": "test/fixtures/users/post_users_id_email_aliases.json",
    "content": "{\n    \"type\": \"email_alias\",\n    \"id\": \"1234\",\n    \"is_confirmed\": true,\n    \"email\": \"dglover2@example.com\"\n}\n"
  },
  {
    "path": "test/fixtures/users/post_users_terminate_sessions.json",
    "content": "{\n    \"message\": \"Request is successful, please check the admin events for the status of the job\"\n}\n"
  },
  {
    "path": "test/fixtures/users/put_users_id.json",
    "content": "{\n    \"type\": \"user\",\n    \"id\": \"33333\",\n    \"name\": \"Test User\",\n    \"login\": \"testuser@example.com\",\n    \"created_at\": \"2016-11-09T15:57:20-08:00\",\n    \"modified_at\": \"2018-04-25T17:07:47-07:00\",\n    \"language\": \"en\",\n    \"timezone\": \"America/Los_Angeles\",\n    \"space_amount\": 1000000000000000,\n    \"space_used\": 38243356,\n    \"max_upload_size\": 5368709120,\n    \"status\": \"active\",\n    \"job_title\": \"CEO\",\n    \"phone\": \"(555) 555-5555\",\n    \"address\": \"\",\n    \"avatar_url\": \"https://app.box.com/api/avatar/large/deprecated\"\n}\n"
  },
  {
    "path": "test/fixtures/users/put_users_id_folder.json",
    "content": "{\n    \"type\": \"folder\",\n    \"id\": \"0\",\n    \"sequence_id\": null,\n    \"etag\": null,\n    \"name\": \"All Files\",\n    \"created_at\": null,\n    \"modified_at\": null,\n    \"description\": \"\",\n    \"size\": 8183737,\n    \"path_collection\": {\n        \"total_count\": 0,\n        \"entries\": []\n    },\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"\",\n        \"name\": \"\",\n        \"login\": \"\"\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"content_created_at\": null,\n    \"content_modified_at\": null,\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"33333\",\n        \"name\": \"Test User\",\n        \"login\": \"testuser@example.com\"\n    },\n    \"shared_link\": null,\n    \"folder_upload_email\": null,\n    \"parent\": null,\n    \"item_status\": \"active\",\n    \"item_collection\": {\n        \"total_count\": 6,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"44444\",\n                \"sequence_id\": \"1\",\n                \"etag\": \"1\",\n                \"name\": \"Collab Folder\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"55555\",\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"name\": \"Copied Folder\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"66666\",\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"name\": \"SDK Test Folder\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"77777\",\n                \"sequence_id\": \"1\",\n                \"etag\": \"1\",\n                \"name\": \"Test Folder\"\n            },\n            {\n                \"type\": \"file\",\n                \"id\": \"88888\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"888880\",\n                    \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\"\n                },\n                \"sequence_id\": \"0\",\n                \"etag\": \"0\",\n                \"sha1\": \"6afc05eae22e994f1c7dd48e58f8895dd9028223\",\n                \"name\": \"Copied file.txt\"\n            },\n            {\n                \"type\": \"file\",\n                \"id\": \"99999\",\n                \"file_version\": {\n                    \"type\": \"file_version\",\n                    \"id\": \"999990\",\n                    \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\"\n                },\n                \"sequence_id\": \"9\",\n                \"etag\": \"9\",\n                \"sha1\": \"97cc02de7c356f94e3beeb1e0c63f78a6edb01fd\",\n                \"name\": \"test file.txt\"\n            }\n        ],\n        \"offset\": 0,\n        \"limit\": 100,\n        \"order\": [\n            {\n                \"by\": \"type\",\n                \"direction\": \"ASC\"\n            },\n            {\n                \"by\": \"name\",\n                \"direction\": \"ASC\"\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": "test/fixtures/watermarking/get_files_id_watermark.json",
    "content": "{\n    \"watermark\": {\n        \"created_at\": \"2018-04-24T17:12:19-07:00\",\n        \"modified_at\": \"2018-04-24T17:12:19-07:00\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/watermarking/put_files_id_watermark.json",
    "content": "{\n    \"watermark\": {\n        \"created_at\": \"2018-04-24T17:12:19-07:00\",\n        \"modified_at\": \"2018-04-24T17:12:19-07:00\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/web-links/get_web_links_id.json",
    "content": "{\n    \"type\": \"web_link\",\n    \"id\": \"6742981\",\n    \"sequence_id\": \"0\",\n    \"etag\": \"0\",\n    \"name\": \"Box Website\",\n    \"url\": \"https://www.box.com\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"10523870\",\n        \"name\": \"Ted Blosser\",\n        \"login\": \"ted+demo@example.com\"\n    },\n    \"created_at\": \"2015-05-07T14:31:16-07:00\",\n    \"modified_at\": \"2015-05-07T14:31:16-07:00\",\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"848123342\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"name\": \"Documentation\"\n    },\n    \"description\": \"Cloud Content Management\",\n    \"item_status\": \"active\",\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"shared_link\": null,\n    \"path_collection\": {\n        \"total_count\": 2,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"848123342\",\n                \"sequence_id\": \"1\",\n                \"etag\": \"1\",\n                \"name\": \"Documentation\"\n            }\n        ]\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"10523870\",\n        \"name\": \"Ted Blosser\",\n        \"login\": \"ted+demo@example.com\"\n    },\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"10523870\",\n        \"name\": \"Ted Blosser\",\n        \"login\": \"ted+demo@example.com\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/web-links/post_web_links.json",
    "content": "{\n    \"type\": \"web_link\",\n    \"id\": \"6743065\",\n    \"sequence_id\": \"0\",\n    \"etag\": \"0\",\n    \"name\": \"Box Website!\",\n    \"url\": \"https://www.box.com\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"10523870\",\n        \"name\": \"Ted Blosser\",\n        \"login\": \"ted+demo@example.com\"\n    },\n    \"created_at\": \"2015-05-07T15:00:01-07:00\",\n    \"modified_at\": \"2015-05-07T15:00:01-07:00\",\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"848123342\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"name\": \"Documentation\"\n    },\n    \"description\": \"Cloud Content Management\",\n    \"item_status\": \"active\",\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"shared_link\": null,\n    \"path_collection\": {\n        \"total_count\": 2,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"848123342\",\n                \"sequence_id\": \"1\",\n                \"etag\": \"1\",\n                \"name\": \"Documentation\"\n            }\n        ]\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"10523870\",\n        \"name\": \"Ted Blosser\",\n        \"login\": \"ted+demo@example.com\"\n    },\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"10523870\",\n        \"name\": \"Ted Blosser\",\n        \"login\": \"ted+demo@example.com\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/web-links/put_web_links_id.json",
    "content": "{\n    \"type\": \"web_link\",\n    \"id\": \"6742981\",\n    \"sequence_id\": \"2\",\n    \"etag\": \"2\",\n    \"name\": \"Box Marketing Web Page\",\n    \"url\": \"https://www.box.com\",\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"10523870\",\n        \"name\": \"Ted Blosser\",\n        \"login\": \"ted+demo@example.com\"\n    },\n    \"created_at\": \"2015-05-07T14:31:16-07:00\",\n    \"modified_at\": \"2015-05-07T15:45:04-07:00\",\n    \"parent\": {\n        \"type\": \"folder\",\n        \"id\": \"848123342\",\n        \"sequence_id\": \"1\",\n        \"etag\": \"1\",\n        \"name\": \"Documentation\"\n    },\n    \"description\": \"Cloud Content Management\",\n    \"item_status\": \"active\",\n    \"trashed_at\": null,\n    \"purged_at\": null,\n    \"shared_link\": null,\n    \"path_collection\": {\n        \"total_count\": 2,\n        \"entries\": [\n            {\n                \"type\": \"folder\",\n                \"id\": \"0\",\n                \"sequence_id\": null,\n                \"etag\": null,\n                \"name\": \"All Files\"\n            },\n            {\n                \"type\": \"folder\",\n                \"id\": \"848123342\",\n                \"sequence_id\": \"1\",\n                \"etag\": \"1\",\n                \"name\": \"Documentation\"\n            }\n        ]\n    },\n    \"modified_by\": {\n        \"type\": \"user\",\n        \"id\": \"10523870\",\n        \"name\": \"Ted Blosser\",\n        \"login\": \"ted+demo@example.com\"\n    },\n    \"owned_by\": {\n        \"type\": \"user\",\n        \"id\": \"10523870\",\n        \"name\": \"Ted Blosser\",\n        \"login\": \"ted+demo@example.com\"\n    }\n}\n"
  },
  {
    "path": "test/fixtures/webhooks/get_webhooks_id.json",
    "content": "{\n    \"id\": \"1234\",\n    \"type\": \"webhook\",\n    \"target\": {\n        \"id\": \"5018848529\",\n        \"type\": \"file\"\n    },\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"2030392653\",\n        \"name\": \"John Q. Developer\",\n        \"login\": \"johnq@example.net\"\n    },\n    \"created_at\": \"2016-05-04T18:51:45-07:00\",\n    \"address\": \"https://example.net/actions/file_changed\",\n    \"triggers\": [\n        \"FILE.PREVIEWED\"\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/webhooks/get_webhooks_page_1.json",
    "content": "{\n    \"next_marker\": \"ZmlQZS0xLTE%3D\",\n    \"entries\": [\n        {\n            \"id\": \"4161\",\n            \"type\": \"webhook\",\n            \"target\": {\n                \"id\": \"5018326685\",\n                \"type\": \"folder\"\n            }\n        },\n        {\n            \"id\": \"4165\",\n            \"type\": \"webhook\",\n            \"target\": {\n                \"id\": \"5016243669\",\n                \"type\": \"file\"\n            }\n        }\n    ],\n    \"limit\": 2\n}\n"
  },
  {
    "path": "test/fixtures/webhooks/get_webhooks_page_2.json",
    "content": "{\n    \"next_marker\": \"\",\n    \"entries\": [\n        {\n            \"id\": \"41611\",\n            \"type\": \"webhook\",\n            \"target\": {\n                \"id\": \"5018326685\",\n                \"type\": \"folder\"\n            }\n        },\n        {\n            \"id\": \"41651\",\n            \"type\": \"webhook\",\n            \"target\": {\n                \"id\": \"5016243669\",\n                \"type\": \"file\"\n            }\n        }\n     ],\n    \"limit\": 2\n}\n"
  },
  {
    "path": "test/fixtures/webhooks/post_webhooks.json",
    "content": "{\n    \"id\": \"1234\",\n    \"type\": \"webhook\",\n    \"target\": {\n        \"id\": \"5016243669\",\n        \"type\": \"file\"\n    },\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"2030392653\",\n        \"name\": \"John Q. Developer\",\n        \"login\": \"johnq@dev.name\"\n    },\n    \"created_at\": \"2016-05-09T17:41:27-07:00\",\n    \"address\": \"https://dev.name/actions/file_changed\",\n    \"triggers\": [\n        \"FILE.DOWNLOADED\",\n        \"FILE.UPLOADED\"\n    ]\n}\n"
  },
  {
    "path": "test/fixtures/webhooks/put_webhooks_id.json",
    "content": "{\n    \"id\": \"1234\",\n    \"type\": \"webhook\",\n    \"target\": {\n        \"id\": \"5016243669\",\n        \"type\": \"file\"\n    },\n    \"created_by\": {\n        \"type\": \"user\",\n        \"id\": \"2030392653\",\n        \"name\": \"John Q. Developer\",\n        \"login\": \"johnq@dev.name\"\n    },\n    \"created_at\": \"2016-05-09T17:41:27-07:00\",\n    \"address\": \"https://dev.name/actions/file_changed\",\n    \"triggers\": [\n        \"FILE.DOWNLOADED\",\n        \"FILE.UPLOADED\"\n    ]\n}\n"
  },
  {
    "path": "test/github-updater.test.js",
    "content": "'use strict';\n\nconst assert = require('chai').assert;\nconst sinon = require('sinon');\nconst GitHubUpdater = require('../src/github-updater');\nconst fs = require('node:fs');\nconst path = require('node:path');\n\n// Helper function to create a mock config with required methods\nfunction createMockConfig(overrides = {}) {\n\treturn {\n\t\tscopedEnvVar: sinon.stub().returns(),\n\t\tscopedEnvVarKey: sinon.stub().returns('TEST_VAR'),\n\t\ts3Key: sinon.stub().returns('test-key'),\n\t\tcacheDir: '/tmp/cache',\n\t\tdataDir: '/tmp/data',\n\t\troot: '/tmp/root',\n\t\tname: 'boxcli',\n\t\tversion: '1.0.0',\n\t\tbin: 'box',\n\t\tplatform: 'darwin',\n\t\tarch: 'x64',\n\t\t...overrides,\n\t};\n}\n\ndescribe('GitHubUpdater', function () {\n\tlet sandbox;\n\n\tbeforeEach(function () {\n\t\tsandbox = sinon.createSandbox();\n\t});\n\n\tafterEach(function () {\n\t\tsandbox.restore();\n\t});\n\n\tdescribe('getGitHubConfig', function () {\n\t\tit('should return owner and repo from oclif.update.github config', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tconst config = updater.getGitHubConfig();\n\n\t\t\tassert.deepEqual(config, {\n\t\t\t\towner: 'box',\n\t\t\t\trepo: 'boxcli',\n\t\t\t});\n\t\t});\n\n\t\tit('should parse owner and repo from repository string (owner/repo format)', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {},\n\t\t\t\t\trepository: 'box/boxcli',\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tconst config = updater.getGitHubConfig();\n\n\t\t\tassert.deepEqual(config, {\n\t\t\t\towner: 'box',\n\t\t\t\trepo: 'boxcli',\n\t\t\t});\n\t\t});\n\n\t\tit('should parse owner and repo from repository string (github: prefix)', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {},\n\t\t\t\t\trepository: 'github:box/boxcli',\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tconst config = updater.getGitHubConfig();\n\n\t\t\tassert.deepEqual(config, {\n\t\t\t\towner: 'box',\n\t\t\t\trepo: 'boxcli',\n\t\t\t});\n\t\t});\n\n\t\tit('should parse owner and repo from repository string (.git suffix)', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {},\n\t\t\t\t\trepository: 'box/boxcli.git',\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tconst config = updater.getGitHubConfig();\n\n\t\t\tassert.deepEqual(config, {\n\t\t\t\towner: 'box',\n\t\t\t\trepo: 'boxcli',\n\t\t\t});\n\t\t});\n\n\t\tit('should parse owner and repo from repository URL', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {},\n\t\t\t\t\trepository: 'https://github.com/box/boxcli',\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tconst config = updater.getGitHubConfig();\n\n\t\t\tassert.deepEqual(config, {\n\t\t\t\towner: 'box',\n\t\t\t\trepo: 'boxcli',\n\t\t\t});\n\t\t});\n\n\t\tit('should parse owner and repo from repository URL with .git suffix', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {},\n\t\t\t\t\trepository: 'https://github.com/box/boxcli.git',\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tconst config = updater.getGitHubConfig();\n\n\t\t\tassert.deepEqual(config, {\n\t\t\t\towner: 'box',\n\t\t\t\trepo: 'boxcli',\n\t\t\t});\n\t\t});\n\n\t\tit('should throw error when GitHub config is not found', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {},\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tassert.throws(() => {\n\t\t\t\tnew GitHubUpdater(mockConfig);\n\t\t\t}, /GitHub repository not configured/);\n\t\t});\n\n\t\tit('should throw error when repository is not a GitHub URL', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {},\n\t\t\t\t\trepository: 'https://gitlab.com/box/boxcli',\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tassert.throws(() => {\n\t\t\t\tnew GitHubUpdater(mockConfig);\n\t\t\t}, /GitHub repository not configured/);\n\t\t});\n\n\t\tit('should prioritize oclif.update.github over repository field', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\trepository: 'other/repo',\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tconst config = updater.getGitHubConfig();\n\n\t\t\tassert.deepEqual(config, {\n\t\t\t\towner: 'box',\n\t\t\t\trepo: 'boxcli',\n\t\t\t});\n\t\t});\n\n\t\tit('should throw error when github config is incomplete (missing repo)', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tassert.throws(() => {\n\t\t\t\tnew GitHubUpdater(mockConfig);\n\t\t\t}, /GitHub repository not configured/);\n\t\t});\n\n\t\tit('should throw error when github config is incomplete (missing owner)', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tassert.throws(() => {\n\t\t\t\tnew GitHubUpdater(mockConfig);\n\t\t\t}, /GitHub repository not configured/);\n\t\t});\n\t});\n\n\tdescribe('determineAssetName', function () {\n\t\tit('should generate correct asset name for darwin platform', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tbin: 'box',\n\t\t\t\tplatform: 'darwin',\n\t\t\t\tarch: 'x64',\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tconst assetName = updater.determineAssetName('1.0.0');\n\n\t\t\tassert.equal(assetName, 'box-v1.0.0-darwin-x64.tar.gz');\n\t\t});\n\n\t\tit('should generate correct asset name for linux platform', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tbin: 'box',\n\t\t\t\tplatform: 'linux',\n\t\t\t\tarch: 'x64',\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tconst assetName = updater.determineAssetName('2.5.0');\n\n\t\t\tassert.equal(assetName, 'box-v2.5.0-linux-x64.tar.gz');\n\t\t});\n\n\t\tit('should generate correct asset name for windows platform', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tbin: 'box',\n\t\t\t\tplatform: 'win32',\n\t\t\t\tarch: 'x64',\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tconst assetName = updater.determineAssetName('3.0.0');\n\n\t\t\tassert.equal(assetName, 'box-v3.0.0-win32-x64.tar.gz');\n\t\t});\n\n\t\tit('should convert wsl platform to linux', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tbin: 'box',\n\t\t\t\tplatform: 'wsl',\n\t\t\t\tarch: 'x64',\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tconst assetName = updater.determineAssetName('1.0.0');\n\n\t\t\tassert.equal(assetName, 'box-v1.0.0-linux-x64.tar.gz');\n\t\t});\n\n\t\tit('should generate correct asset name for arm64 architecture', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tbin: 'box',\n\t\t\t\tplatform: 'darwin',\n\t\t\t\tarch: 'arm64',\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tconst assetName = updater.determineAssetName('1.5.0');\n\n\t\t\tassert.equal(assetName, 'box-v1.5.0-darwin-arm64.tar.gz');\n\t\t});\n\n\t\tit('should use custom bin name in asset', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tbin: 'customcli',\n\t\t\t\tplatform: 'darwin',\n\t\t\t\tarch: 'x64',\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tconst assetName = updater.determineAssetName('2.0.0');\n\n\t\t\tassert.equal(assetName, 'customcli-v2.0.0-darwin-x64.tar.gz');\n\t\t});\n\n\t\tit('should generate correct asset name for linux arm64', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tbin: 'box',\n\t\t\t\tplatform: 'linux',\n\t\t\t\tarch: 'arm64',\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tconst assetName = updater.determineAssetName('3.2.1');\n\n\t\t\tassert.equal(assetName, 'box-v3.2.1-linux-arm64.tar.gz');\n\t\t});\n\t});\n\n\tdescribe('constructor', function () {\n\t\tit('should initialize with null octokit', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\tassert.isNull(updater.octokit);\n\t\t\tassert.exists(updater.githubConfig);\n\t\t});\n\n\t\tit('should store githubConfig from getGitHubConfig', function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\tassert.deepEqual(updater.githubConfig, {\n\t\t\t\towner: 'box',\n\t\t\t\trepo: 'boxcli',\n\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('GitHub API Integration Tests', function () {\n\t\tlet mockReleaseData;\n\n\t\tbeforeEach(function () {\n\t\t\t// Load the real GitHub API response\n\t\t\tconst fixtureData = fs.readFileSync(\n\t\t\t\tpath.join(__dirname, 'fixtures/github/releases-v4.4.1.json'),\n\t\t\t\t'utf8'\n\t\t\t);\n\t\t\tmockReleaseData = JSON.parse(fixtureData);\n\t\t});\n\n\t\tdescribe('fetchGitHubVersionIndex', function () {\n\t\t\tit('should parse GitHub releases and create version index', async function () {\n\t\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\t\tpjson: {\n\t\t\t\t\t\toclif: {\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbin: 'box',\n\t\t\t\t\tplatform: 'darwin',\n\t\t\t\t\tarch: 'x64',\n\t\t\t\t});\n\n\t\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\t\t// Mock the Octokit API\n\t\t\t\tconst mockOctokit = {\n\t\t\t\t\trepos: {\n\t\t\t\t\t\tlistReleases: sinon\n\t\t\t\t\t\t\t.stub()\n\t\t\t\t\t\t\t.resolves({ data: mockReleaseData }),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t\tconst versionIndex = await updater.fetchGitHubVersionIndex();\n\n\t\t\t\tassert.isObject(versionIndex);\n\t\t\t\tassert.property(versionIndex, '4.4.1');\n\t\t\t\tassert.equal(\n\t\t\t\t\tversionIndex['4.4.1'],\n\t\t\t\t\t'https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-darwin-x64.tar.gz'\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tit('should find correct asset for darwin arm64', async function () {\n\t\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\t\tpjson: {\n\t\t\t\t\t\toclif: {\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbin: 'box',\n\t\t\t\t\tplatform: 'darwin',\n\t\t\t\t\tarch: 'arm64',\n\t\t\t\t});\n\n\t\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\t\tconst mockOctokit = {\n\t\t\t\t\trepos: {\n\t\t\t\t\t\tlistReleases: sinon\n\t\t\t\t\t\t\t.stub()\n\t\t\t\t\t\t\t.resolves({ data: mockReleaseData }),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t\tconst versionIndex = await updater.fetchGitHubVersionIndex();\n\n\t\t\t\tassert.equal(\n\t\t\t\t\tversionIndex['4.4.1'],\n\t\t\t\t\t'https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-darwin-arm64.tar.gz'\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tit('should find correct asset for windows x64', async function () {\n\t\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\t\tpjson: {\n\t\t\t\t\t\toclif: {\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbin: 'box',\n\t\t\t\t\tplatform: 'win32',\n\t\t\t\t\tarch: 'x64',\n\t\t\t\t});\n\n\t\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\t\tconst mockOctokit = {\n\t\t\t\t\trepos: {\n\t\t\t\t\t\tlistReleases: sinon\n\t\t\t\t\t\t\t.stub()\n\t\t\t\t\t\t\t.resolves({ data: mockReleaseData }),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t\tconst versionIndex = await updater.fetchGitHubVersionIndex();\n\n\t\t\t\tassert.equal(\n\t\t\t\t\tversionIndex['4.4.1'],\n\t\t\t\t\t'https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-win32-x64.tar.gz'\n\t\t\t\t);\n\t\t\t});\n\t\t});\n\n\t\tdescribe('fetchGitHubManifest', function () {\n\t\t\tit('should fetch latest release manifest when no version specified', async function () {\n\t\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\t\tpjson: {\n\t\t\t\t\t\toclif: {\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbin: 'box',\n\t\t\t\t\tplatform: 'darwin',\n\t\t\t\t\tarch: 'x64',\n\t\t\t\t});\n\n\t\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\t\tconst mockOctokit = {\n\t\t\t\t\trepos: {\n\t\t\t\t\t\tgetLatestRelease: sinon\n\t\t\t\t\t\t\t.stub()\n\t\t\t\t\t\t\t.resolves({ data: mockReleaseData[0] }),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t\tconst manifest = await updater.fetchGitHubManifest();\n\n\t\t\t\tassert.isObject(manifest);\n\t\t\t\tassert.equal(manifest.version, '4.4.1');\n\t\t\t\tassert.equal(\n\t\t\t\t\tmanifest.gz,\n\t\t\t\t\t'https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-darwin-x64.tar.gz'\n\t\t\t\t);\n\t\t\t\tassert.equal(\n\t\t\t\t\tmanifest.sha256gz,\n\t\t\t\t\t'8dac71613287363ffca3dcb7d84805142cb4d10878f03b4fcda3916d660138d2'\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tit('should fetch correct asset for different architectures', async function () {\n\t\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\t\tpjson: {\n\t\t\t\t\t\toclif: {\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbin: 'box',\n\t\t\t\t\tplatform: 'darwin',\n\t\t\t\t\tarch: 'arm64',\n\t\t\t\t});\n\n\t\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\t\tconst mockOctokit = {\n\t\t\t\t\trepos: {\n\t\t\t\t\t\tgetLatestRelease: sinon\n\t\t\t\t\t\t\t.stub()\n\t\t\t\t\t\t\t.resolves({ data: mockReleaseData[0] }),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t\tconst manifest = await updater.fetchGitHubManifest();\n\n\t\t\t\tassert.isObject(manifest);\n\t\t\t\tassert.equal(manifest.version, '4.4.1');\n\t\t\t\tassert.equal(\n\t\t\t\t\tmanifest.gz,\n\t\t\t\t\t'https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-darwin-arm64.tar.gz'\n\t\t\t\t);\n\t\t\t\tassert.equal(\n\t\t\t\t\tmanifest.sha256gz,\n\t\t\t\t\t'716923f5a7c32f5344662eb10e2f10f9d89fb008e1d418b99cbcbe4247c1bc6f'\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tit('should throw error when asset not found for platform', async function () {\n\t\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\t\tpjson: {\n\t\t\t\t\t\toclif: {\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbin: 'box',\n\t\t\t\t\tplatform: 'linux',\n\t\t\t\t\tarch: 'x64',\n\t\t\t\t});\n\n\t\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\t\tconst mockOctokit = {\n\t\t\t\t\trepos: {\n\t\t\t\t\t\tgetLatestRelease: sinon\n\t\t\t\t\t\t\t.stub()\n\t\t\t\t\t\t\t.resolves({ data: mockReleaseData[0] }),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t\ttry {\n\t\t\t\t\tawait updater.fetchGitHubManifest();\n\t\t\t\t\tassert.fail('Should have thrown an error');\n\t\t\t\t} catch (error) {\n\t\t\t\t\tassert.include(error.message, 'No suitable asset found');\n\t\t\t\t\tassert.include(error.message, 'linux-x64');\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tit('should fetch specific version manifest when version provided', async function () {\n\t\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\t\tpjson: {\n\t\t\t\t\t\toclif: {\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbin: 'box',\n\t\t\t\t\tplatform: 'win32',\n\t\t\t\t\tarch: 'arm64',\n\t\t\t\t});\n\n\t\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\t\tconst mockOctokit = {\n\t\t\t\t\trepos: {\n\t\t\t\t\t\tgetReleaseByTag: sinon\n\t\t\t\t\t\t\t.stub()\n\t\t\t\t\t\t\t.resolves({ data: mockReleaseData[0] }),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t\tconst manifest = await updater.fetchGitHubManifest(\n\t\t\t\t\t'4.4.1',\n\t\t\t\t\t'https://fallback-url.com/asset.tar.gz'\n\t\t\t\t);\n\n\t\t\t\tassert.isObject(manifest);\n\t\t\t\tassert.equal(manifest.version, '4.4.1');\n\t\t\t\tassert.equal(\n\t\t\t\t\tmanifest.gz,\n\t\t\t\t\t'https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-win32-arm64.tar.gz'\n\t\t\t\t);\n\t\t\t\tassert.equal(\n\t\t\t\t\tmanifest.sha256gz,\n\t\t\t\t\t'52b3e75426d0de2b0c4343e36ae125f1124cc748899675681957f0770647f301'\n\t\t\t\t);\n\t\t\t});\n\n\t\t\tit('should fallback to provided URL when asset not found', async function () {\n\t\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\t\tpjson: {\n\t\t\t\t\t\toclif: {\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbin: 'box',\n\t\t\t\t\tplatform: 'linux',\n\t\t\t\t\tarch: 'x64',\n\t\t\t\t});\n\n\t\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\t\tconst mockOctokit = {\n\t\t\t\t\trepos: {\n\t\t\t\t\t\tgetReleaseByTag: sinon\n\t\t\t\t\t\t\t.stub()\n\t\t\t\t\t\t\t.resolves({ data: mockReleaseData[0] }),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t\tconst fallbackUrl =\n\t\t\t\t\t'https://fallback-url.com/box-v4.4.1.tar.gz';\n\t\t\t\tconst manifest = await updater.fetchGitHubManifest(\n\t\t\t\t\t'4.4.1',\n\t\t\t\t\tfallbackUrl\n\t\t\t\t);\n\n\t\t\t\tassert.isObject(manifest);\n\t\t\t\tassert.equal(manifest.version, '4.4.1');\n\t\t\t\tassert.equal(manifest.gz, fallbackUrl);\n\t\t\t});\n\n\t\t\tit('should fallback to provided URL on API error', async function () {\n\t\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\t\tpjson: {\n\t\t\t\t\t\toclif: {\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbin: 'box',\n\t\t\t\t\tplatform: 'darwin',\n\t\t\t\t\tarch: 'x64',\n\t\t\t\t});\n\n\t\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\t\tconst mockOctokit = {\n\t\t\t\t\trepos: {\n\t\t\t\t\t\tgetReleaseByTag: sinon\n\t\t\t\t\t\t\t.stub()\n\t\t\t\t\t\t\t.rejects(new Error('API Error')),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t\tconst fallbackUrl =\n\t\t\t\t\t'https://fallback-url.com/box-v4.4.1.tar.gz';\n\t\t\t\tconst manifest = await updater.fetchGitHubManifest(\n\t\t\t\t\t'4.4.1',\n\t\t\t\t\tfallbackUrl\n\t\t\t\t);\n\n\t\t\t\tassert.isObject(manifest);\n\t\t\t\tassert.equal(manifest.version, '4.4.1');\n\t\t\t\tassert.equal(manifest.gz, fallbackUrl);\n\t\t\t});\n\n\t\t\tit('should throw error with 404 status when release not found', async function () {\n\t\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\t\tpjson: {\n\t\t\t\t\t\toclif: {\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbin: 'box',\n\t\t\t\t\tplatform: 'darwin',\n\t\t\t\t\tarch: 'x64',\n\t\t\t\t});\n\n\t\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\t\tconst notFoundError = new Error('Not Found');\n\t\t\t\tnotFoundError.status = 404;\n\n\t\t\t\tconst mockOctokit = {\n\t\t\t\t\trepos: {\n\t\t\t\t\t\tgetReleaseByTag: sinon.stub().rejects(notFoundError),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t\ttry {\n\t\t\t\t\tawait updater.fetchGitHubManifest('99.99.99');\n\t\t\t\t\tassert.fail('Should have thrown an error');\n\t\t\t\t} catch (error) {\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\terror.message,\n\t\t\t\t\t\t'Release v99.99.99 not found'\n\t\t\t\t\t);\n\t\t\t\t\tassert.include(error.message, 'box/boxcli');\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tit('should throw error for 404 when fetching latest release', async function () {\n\t\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\t\tpjson: {\n\t\t\t\t\t\toclif: {\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbin: 'box',\n\t\t\t\t\tplatform: 'darwin',\n\t\t\t\t\tarch: 'x64',\n\t\t\t\t});\n\n\t\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\t\tconst notFoundError = new Error('Not Found');\n\t\t\t\tnotFoundError.status = 404;\n\n\t\t\t\tconst mockOctokit = {\n\t\t\t\t\trepos: {\n\t\t\t\t\t\tgetLatestRelease: sinon.stub().rejects(notFoundError),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t\ttry {\n\t\t\t\t\tawait updater.fetchGitHubManifest();\n\t\t\t\t\tassert.fail('Should have thrown an error');\n\t\t\t\t} catch (error) {\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\terror.message,\n\t\t\t\t\t\t'Release not found in box/boxcli'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tit('should handle manifest without SHA256 digest', async function () {\n\t\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\t\tpjson: {\n\t\t\t\t\t\toclif: {\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbin: 'box',\n\t\t\t\t\tplatform: 'darwin',\n\t\t\t\t\tarch: 'x64',\n\t\t\t\t});\n\n\t\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\t\tconst releaseWithoutDigest = {\n\t\t\t\t\t...mockReleaseData[0],\n\t\t\t\t\tassets: mockReleaseData[0].assets.map((asset) => ({\n\t\t\t\t\t\t...asset,\n\t\t\t\t\t\tdigest: undefined,\n\t\t\t\t\t})),\n\t\t\t\t};\n\n\t\t\t\tconst mockOctokit = {\n\t\t\t\t\trepos: {\n\t\t\t\t\t\tgetLatestRelease: sinon\n\t\t\t\t\t\t\t.stub()\n\t\t\t\t\t\t\t.resolves({ data: releaseWithoutDigest }),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t\tconst manifest = await updater.fetchGitHubManifest();\n\n\t\t\t\tassert.isObject(manifest);\n\t\t\t\tassert.equal(manifest.version, '4.4.1');\n\t\t\t\tassert.isUndefined(manifest.sha256gz);\n\t\t\t});\n\n\t\t\tit('should handle manifest with invalid digest format', async function () {\n\t\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\t\tpjson: {\n\t\t\t\t\t\toclif: {\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbin: 'box',\n\t\t\t\t\tplatform: 'darwin',\n\t\t\t\t\tarch: 'x64',\n\t\t\t\t});\n\n\t\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\t\tconst releaseWithInvalidDigest = {\n\t\t\t\t\t...mockReleaseData[0],\n\t\t\t\t\tassets: mockReleaseData[0].assets.map((asset) =>\n\t\t\t\t\t\tasset.name === 'box-v4.4.1-darwin-x64.tar.gz'\n\t\t\t\t\t\t\t? {\n\t\t\t\t\t\t\t\t\t...asset,\n\t\t\t\t\t\t\t\t\tdigest: 'md5:somehash',\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t: asset\n\t\t\t\t\t),\n\t\t\t\t};\n\n\t\t\t\tconst mockOctokit = {\n\t\t\t\t\trepos: {\n\t\t\t\t\t\tgetLatestRelease: sinon\n\t\t\t\t\t\t\t.stub()\n\t\t\t\t\t\t\t.resolves({ data: releaseWithInvalidDigest }),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t\tconst manifest = await updater.fetchGitHubManifest();\n\n\t\t\t\tassert.isObject(manifest);\n\t\t\t\tassert.equal(manifest.version, '4.4.1');\n\t\t\t\tassert.isUndefined(manifest.sha256gz);\n\t\t\t});\n\t\t});\n\n\t\tdescribe('fetchVersionIndex', function () {\n\t\t\tit('should delegate to fetchGitHubVersionIndex', async function () {\n\t\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\t\tpjson: {\n\t\t\t\t\t\toclif: {\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbin: 'box',\n\t\t\t\t\tplatform: 'darwin',\n\t\t\t\t\tarch: 'x64',\n\t\t\t\t});\n\n\t\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\t\tconst mockOctokit = {\n\t\t\t\t\trepos: {\n\t\t\t\t\t\tlistReleases: sinon\n\t\t\t\t\t\t\t.stub()\n\t\t\t\t\t\t\t.resolves({ data: mockReleaseData }),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t\tconst versionIndex = await updater.fetchVersionIndex();\n\n\t\t\t\tassert.isObject(versionIndex);\n\t\t\t\tassert.property(versionIndex, '4.4.1');\n\t\t\t});\n\t\t});\n\n\t\tdescribe('GitHub API error handling', function () {\n\t\t\tit('should throw error when GitHub API fails for version index', async function () {\n\t\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\t\tpjson: {\n\t\t\t\t\t\toclif: {\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbin: 'box',\n\t\t\t\t\tplatform: 'darwin',\n\t\t\t\t\tarch: 'x64',\n\t\t\t\t});\n\n\t\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\t\tconst mockOctokit = {\n\t\t\t\t\trepos: {\n\t\t\t\t\t\tlistReleases: sinon\n\t\t\t\t\t\t\t.stub()\n\t\t\t\t\t\t\t.rejects(new Error('API Error')),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t\ttry {\n\t\t\t\t\tawait updater.fetchGitHubVersionIndex();\n\t\t\t\t\tassert.fail('Should have thrown an error');\n\t\t\t\t} catch (error) {\n\t\t\t\t\tassert.include(\n\t\t\t\t\t\terror.message,\n\t\t\t\t\t\t'Failed to fetch releases from GitHub repository box/boxcli'\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t});\n\n\t\t\tit('should handle empty releases list', async function () {\n\t\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\t\tpjson: {\n\t\t\t\t\t\toclif: {\n\t\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t\tbin: 'box',\n\t\t\t\t\tplatform: 'darwin',\n\t\t\t\t\tarch: 'x64',\n\t\t\t\t});\n\n\t\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\n\t\t\t\tconst mockOctokit = {\n\t\t\t\t\trepos: {\n\t\t\t\t\t\tlistReleases: sinon.stub().resolves({ data: [] }),\n\t\t\t\t\t},\n\t\t\t\t};\n\t\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t\tconst versionIndex = await updater.fetchGitHubVersionIndex();\n\n\t\t\t\tassert.isObject(versionIndex);\n\t\t\t\tassert.isEmpty(versionIndex);\n\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('ensureOctokit', function () {\n\t\tit('should initialize octokit if not already initialized', async function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tassert.isNull(updater.octokit);\n\n\t\t\tawait updater.ensureOctokit();\n\n\t\t\tassert.isNotNull(updater.octokit);\n\t\t});\n\n\t\tit('should not reinitialize octokit if already set', async function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tconst mockOctokit = { repos: {} };\n\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\tawait updater.ensureOctokit();\n\n\t\t\tassert.strictEqual(updater.octokit, mockOctokit);\n\t\t});\n\t});\n\n\tdescribe('runUpdate', function () {\n\t\tlet mockConfig;\n\t\tlet updater;\n\t\tlet mockOctokit;\n\t\tlet uxActionStartStub;\n\t\tlet uxActionStopStub;\n\n\t\tbeforeEach(function () {\n\t\t\tmockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tbin: 'box',\n\t\t\t\tplatform: 'darwin',\n\t\t\t\tarch: 'x64',\n\t\t\t\trunHook: sinon.stub().resolves(),\n\t\t\t});\n\n\t\t\tupdater = new GitHubUpdater(mockConfig);\n\n\t\t\tmockOctokit = {\n\t\t\t\trepos: {\n\t\t\t\t\tgetLatestRelease: sinon.stub().resolves({ data: {} }),\n\t\t\t\t\tgetReleaseByTag: sinon.stub().resolves({ data: {} }),\n\t\t\t\t},\n\t\t\t};\n\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\t// Stub ux methods\n\t\t\tconst { ux } = require('@oclif/core');\n\t\t\tuxActionStartStub = sandbox.stub(ux.action, 'start');\n\t\t\tuxActionStopStub = sandbox.stub(ux.action, 'stop');\n\t\t});\n\n\t\tit('should stop early if not updatable', async function () {\n\t\t\tsandbox.stub(updater, 'notUpdatable').returns(true);\n\n\t\t\tawait updater.runUpdate({ autoUpdate: false, force: false });\n\n\t\t\tassert.isTrue(uxActionStartStub.called);\n\t\t\tassert.isTrue(uxActionStopStub.calledWith('not updatable'));\n\t\t});\n\n\t\tit('should debounce when autoUpdate is true', async function () {\n\t\t\tconst debounceStub = sandbox.stub(updater, 'debounce').resolves();\n\t\t\tsandbox.stub(updater, 'notUpdatable').returns(true);\n\n\t\t\tawait updater.runUpdate({ autoUpdate: true, force: false });\n\n\t\t\tassert.isTrue(debounceStub.called);\n\t\t});\n\n\t\tit('should skip update if already on version', async function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tbin: 'box',\n\t\t\t\tplatform: 'darwin',\n\t\t\t\tarch: 'x64',\n\t\t\t\tversion: '4.4.1',\n\t\t\t\trunHook: sinon.stub().resolves(),\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\tsandbox.stub(updater, 'notUpdatable').returns(false);\n\t\t\tsandbox.stub(updater, 'determineCurrentVersion').resolves('4.4.1');\n\t\t\tsandbox.stub(updater, 'alreadyOnVersion').returns(true);\n\n\t\t\tconst fixtureData = fs.readFileSync(\n\t\t\t\tpath.join(__dirname, 'fixtures/github/releases-v4.4.1.json'),\n\t\t\t\t'utf8'\n\t\t\t);\n\t\t\tconst mockReleaseData = JSON.parse(fixtureData);\n\n\t\t\tmockOctokit.repos.getLatestRelease = sinon\n\t\t\t\t.stub()\n\t\t\t\t.resolves({ data: mockReleaseData[0] });\n\n\t\t\tawait updater.runUpdate({ autoUpdate: false, force: false });\n\n\t\t\tassert.isTrue(\n\t\t\t\tuxActionStopStub.calledWith(sinon.match(/already on version/))\n\t\t\t);\n\t\t});\n\n\t\tit('should update to specific version with force flag', async function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tbin: 'box',\n\t\t\t\tplatform: 'darwin',\n\t\t\t\tarch: 'x64',\n\t\t\t\tversion: '4.4.0',\n\t\t\t\trunHook: sinon.stub().resolves(),\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\tsandbox.stub(updater, 'notUpdatable').returns(false);\n\t\t\tsandbox.stub(updater, 'determineCurrentVersion').resolves('4.4.0');\n\t\t\tsandbox.stub(updater, 'alreadyOnVersion').returns(false);\n\t\t\tsandbox.stub(updater, 'findLocalVersion').resolves(null);\n\t\t\tsandbox.stub(updater, 'update').resolves();\n\t\t\tsandbox.stub(updater, 'touch').resolves();\n\t\t\tsandbox.stub(updater, 'tidy').resolves();\n\n\t\t\tconst fixtureData = fs.readFileSync(\n\t\t\t\tpath.join(__dirname, 'fixtures/github/releases-v4.4.1.json'),\n\t\t\t\t'utf8'\n\t\t\t);\n\t\t\tconst mockReleaseData = JSON.parse(fixtureData);\n\n\t\t\tconst fetchVersionIndexStub = sandbox\n\t\t\t\t.stub(updater, 'fetchVersionIndex')\n\t\t\t\t.resolves({\n\t\t\t\t\t'4.4.1':\n\t\t\t\t\t\t'https://github.com/box/boxcli/releases/download/v4.4.1/box-v4.4.1-darwin-x64.tar.gz',\n\t\t\t\t});\n\n\t\t\tmockOctokit.repos.getReleaseByTag = sinon\n\t\t\t\t.stub()\n\t\t\t\t.resolves({ data: mockReleaseData[0] });\n\n\t\t\tawait updater.runUpdate({\n\t\t\t\tautoUpdate: false,\n\t\t\t\tforce: true,\n\t\t\t\tversion: '4.4.1',\n\t\t\t});\n\n\t\t\tassert.isTrue(fetchVersionIndexStub.called);\n\t\t\tassert.isTrue(mockConfig.runHook.calledWith('preupdate'));\n\t\t\tassert.isTrue(mockConfig.runHook.calledWith('update'));\n\t\t});\n\n\t\tit('should update to existing local version', async function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tbin: 'box',\n\t\t\t\tplatform: 'darwin',\n\t\t\t\tarch: 'x64',\n\t\t\t\tversion: '4.4.0',\n\t\t\t\trunHook: sinon.stub().resolves(),\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\tsandbox.stub(updater, 'notUpdatable').returns(false);\n\t\t\tsandbox.stub(updater, 'determineCurrentVersion').resolves('4.4.0');\n\t\t\tsandbox.stub(updater, 'alreadyOnVersion').returns(false);\n\t\t\tsandbox\n\t\t\t\t.stub(updater, 'findLocalVersion')\n\t\t\t\t.resolves('/path/to/local/4.4.1');\n\t\t\tsandbox.stub(updater, 'updateToExistingVersion').resolves();\n\t\t\tsandbox.stub(updater, 'touch').resolves();\n\t\t\tsandbox.stub(updater, 'tidy').resolves();\n\n\t\t\tawait updater.runUpdate({\n\t\t\t\tautoUpdate: false,\n\t\t\t\tforce: false,\n\t\t\t\tversion: '4.4.1',\n\t\t\t});\n\n\t\t\tassert.isTrue(mockConfig.runHook.calledWith('preupdate'));\n\t\t\tassert.isTrue(mockConfig.runHook.calledWith('update'));\n\t\t});\n\n\t\tit('should throw error when version not found in index', async function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tbin: 'box',\n\t\t\t\tplatform: 'darwin',\n\t\t\t\tarch: 'x64',\n\t\t\t\tversion: '4.4.0',\n\t\t\t\trunHook: sinon.stub().resolves(),\n\t\t\t});\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\tsandbox.stub(updater, 'notUpdatable').returns(false);\n\t\t\tsandbox.stub(updater, 'determineCurrentVersion').resolves('4.4.0');\n\t\t\tsandbox.stub(updater, 'alreadyOnVersion').returns(false);\n\t\t\tsandbox.stub(updater, 'findLocalVersion').resolves(null);\n\t\t\tsandbox.stub(updater, 'fetchVersionIndex').resolves({\n\t\t\t\t'4.4.1':\n\t\t\t\t\t'https://github.com/box/boxcli/releases/download/v4.4.1',\n\t\t\t});\n\n\t\t\ttry {\n\t\t\t\tawait updater.runUpdate({\n\t\t\t\t\tautoUpdate: false,\n\t\t\t\t\tforce: false,\n\t\t\t\t\tversion: '99.99.99',\n\t\t\t\t});\n\t\t\t\tassert.fail('Should have thrown an error');\n\t\t\t} catch (error) {\n\t\t\t\tassert.include(error.message, '99.99.99 not found in index');\n\t\t\t}\n\t\t});\n\n\t\tit('should use HIDE_UPDATED_MESSAGE env var when already on version', async function () {\n\t\t\tconst mockConfig = createMockConfig({\n\t\t\t\tpjson: {\n\t\t\t\t\toclif: {\n\t\t\t\t\t\tupdate: {\n\t\t\t\t\t\t\tgithub: {\n\t\t\t\t\t\t\t\towner: 'box',\n\t\t\t\t\t\t\t\trepo: 'boxcli',\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t},\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t\tbin: 'box',\n\t\t\t\tplatform: 'darwin',\n\t\t\t\tarch: 'x64',\n\t\t\t\tversion: '4.4.1',\n\t\t\t\trunHook: sinon.stub().resolves(),\n\t\t\t});\n\n\t\t\tmockConfig.scopedEnvVar = sinon\n\t\t\t\t.stub()\n\t\t\t\t.withArgs('HIDE_UPDATED_MESSAGE')\n\t\t\t\t.returns('true');\n\n\t\t\tconst updater = new GitHubUpdater(mockConfig);\n\t\t\tupdater.octokit = mockOctokit;\n\n\t\t\tsandbox.stub(updater, 'notUpdatable').returns(false);\n\t\t\tsandbox.stub(updater, 'determineCurrentVersion').resolves('4.4.1');\n\t\t\tsandbox.stub(updater, 'alreadyOnVersion').returns(true);\n\n\t\t\tconst fixtureData = fs.readFileSync(\n\t\t\t\tpath.join(__dirname, 'fixtures/github/releases-v4.4.1.json'),\n\t\t\t\t'utf8'\n\t\t\t);\n\t\t\tconst mockReleaseData = JSON.parse(fixtureData);\n\n\t\t\tmockOctokit.repos.getLatestRelease = sinon\n\t\t\t\t.stub()\n\t\t\t\t.resolves({ data: mockReleaseData[0] });\n\n\t\t\tawait updater.runUpdate({ autoUpdate: false, force: false });\n\n\t\t\tassert.isTrue(uxActionStopStub.calledWith('done'));\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/helpers/test-helper.js",
    "content": "'use strict';\n\nconst fs = require('node:fs');\nconst path = require('node:path');\nconst os = require('node:os');\n\nconst TEST_API_ROOT = 'https://api.box.com';\nconst TEST_UPLOAD_ROOT = 'https://upload.box.com/api';\nconst TEST_DOWNLOAD_ROOT = 'https://dl.boxcloud.com';\nconst DEFAULT_DOWNLOAD_PATH = path.join(\n\tos.homedir(),\n\t'Downloads/Box-Downloads'\n);\n\nfunction isWin() {\n\treturn process.platform === 'win32';\n}\n\nfunction getFixture(fixture) {\n\tif (!path.extname(fixture)) {\n\t\tfixture += '.json';\n\t}\n\n\tconst content = fs.readFileSync(\n\t\tpath.join(__dirname, '..', `fixtures/${fixture}`),\n\t\t'utf8'\n\t);\n\n\tif (isWin()) {\n\t\tlet transformedContent = fixture.endsWith('table.txt')\n\t\t\t? content.replaceAll(/(?<!-)(?<!\\r\\n)\\r(?!\\n\\r)/g, '')\n\t\t\t: content.replaceAll('\\r', '');\n\n\t\treturn `${transformedContent.trimEnd()}${os.EOL}`;\n\t}\n\n\treturn content;\n}\n\nfunction getProgressBar(message) {\n\treturn process.stderr.isTTY ? message : '';\n}\n\nfunction getBulkProgressBar(size) {\n\treturn getProgressBar(\n\t\t`[----------------------------------------] 0% | 0/${size}[========================================] 100% | ${size}/${size}\\n`\n\t);\n}\n\nfunction getDownloadProgressBar(size) {\n\treturn getProgressBar(\n\t\t`[----------------------------------------] 0% | ETA: 0s | 0/${size} | Speed: N/A MB/s[========================================] 100% | ETA: 0s | ${size}/${size} | Speed: N/A MB/s\\n`\n\t);\n}\n\nfunction getDriveLetter() {\n\treturn process.cwd().split('\\\\')[0];\n}\n\nfunction toUrlPath(filePath) {\n\treturn isWin()\n\t\t? `/${filePath.replace(':', '').replaceAll('\\\\', '/')}`\n\t\t: filePath;\n}\n\nmodule.exports = {\n\tTEST_API_ROOT,\n\tTEST_UPLOAD_ROOT,\n\tTEST_DOWNLOAD_ROOT,\n\tDEFAULT_DOWNLOAD_PATH,\n\tgetFixture,\n\tgetBulkProgressBar,\n\tgetDownloadProgressBar,\n\tgetDriveLetter,\n\tisWin,\n\ttoUrlPath,\n};\n"
  },
  {
    "path": "test/inquirer.test.js",
    "content": "'use strict';\n\nconst { assert } = require('chai');\nconst sinon = require('sinon');\n\nconst handler = () => {};\n\n// The shim in src/inquirer normalizes signal-exit across versions:\n// newer versions export an object with onExit(), while older behavior expects\n// a callable function. These tests assert both compatibility paths.\ndescribe('inquirer compatibility shim', function () {\n\tconst MODULE_UNDER_TEST = '../src/inquirer';\n\tconst signalExitPath = require.resolve('signal-exit');\n\tconst inquirerPath = require.resolve('inquirer');\n\n\tlet originalSignalExitCacheEntry;\n\tlet originalInquirerCacheEntry;\n\n\tbeforeEach(function () {\n\t\t// Snapshot and reset module cache so each test can inject a custom\n\t\t// signal-exit export and re-run the shim from a clean state.\n\t\toriginalSignalExitCacheEntry = require.cache[signalExitPath];\n\t\toriginalInquirerCacheEntry = require.cache[inquirerPath];\n\t\tdelete require.cache[require.resolve(MODULE_UNDER_TEST)];\n\t});\n\n\tafterEach(function () {\n\t\tif (originalSignalExitCacheEntry) {\n\t\t\trequire.cache[signalExitPath] = originalSignalExitCacheEntry;\n\t\t} else {\n\t\t\tdelete require.cache[signalExitPath];\n\t\t}\n\n\t\tif (originalInquirerCacheEntry) {\n\t\t\trequire.cache[inquirerPath] = originalInquirerCacheEntry;\n\t\t} else {\n\t\t\tdelete require.cache[inquirerPath];\n\t\t}\n\n\t\tdelete require.cache[require.resolve(MODULE_UNDER_TEST)];\n\t});\n\n\tit('should wrap object-style signal-exit export as callable function', function () {\n\t\t// Simulate modern signal-exit shape (object export with onExit method).\n\t\tconst onExitStub = sinon.stub().returns('cleanup-callback');\n\t\tconst signalExitObjectExport = {\n\t\t\tonExit: onExitStub,\n\t\t\tload: sinon.stub(),\n\t\t\tunload: sinon.stub(),\n\t\t};\n\n\t\trequire.cache[signalExitPath] = {\n\t\t\tid: signalExitPath,\n\t\t\tfilename: signalExitPath,\n\t\t\tloaded: true,\n\t\t\texports: signalExitObjectExport,\n\t\t};\n\n\t\tconst shimmedInquirer = require(MODULE_UNDER_TEST);\n\t\tconst rawInquirer = require('inquirer');\n\t\tconst patchedSignalExit = require('signal-exit');\n\n\t\t// The shim should not replace inquirer itself; only signal-exit behavior.\n\t\tassert.strictEqual(shimmedInquirer, rawInquirer);\n\t\tassert.strictEqual(typeof patchedSignalExit, 'function');\n\t\tassert.strictEqual(patchedSignalExit.onExit, onExitStub);\n\n\t\tconst result = patchedSignalExit(handler, { alwaysLast: true });\n\t\tassert.strictEqual(result, 'cleanup-callback');\n\t\tassert.isTrue(\n\t\t\tonExitStub.calledOnceWithExactly(handler, { alwaysLast: true })\n\t\t);\n\t});\n\n\tit('should preserve function-style signal-exit export', function () {\n\t\t// If signal-exit is already callable, shim should leave it untouched.\n\t\tconst signalExitFunctionExport = sinon\n\t\t\t.stub()\n\t\t\t.returns('already-callable');\n\n\t\trequire.cache[signalExitPath] = {\n\t\t\tid: signalExitPath,\n\t\t\tfilename: signalExitPath,\n\t\t\tloaded: true,\n\t\t\texports: signalExitFunctionExport,\n\t\t};\n\n\t\trequire(MODULE_UNDER_TEST);\n\t\tconst patchedSignalExit = require('signal-exit');\n\n\t\tassert.strictEqual(patchedSignalExit, signalExitFunctionExport);\n\t\tassert.strictEqual(patchedSignalExit(), 'already-callable');\n\t});\n});\n"
  },
  {
    "path": "test/pagination-utils.test.js",
    "content": "'use strict';\n\nconst paginationUtilities = require('../src/pagination-utils');\nconst assert = require('chai').assert;\nconst { test } = require('@oclif/test');\nconst { getFixture, TEST_API_ROOT } = require('./helpers/test-helper');\n\ndescribe('Pagination', function () {\n\tdescribe('Utilities', function () {\n\t\tit('should set limit to flag value', function () {\n\t\t\tlet flags = { 'max-items': 42 };\n\t\t\tlet options = paginationUtilities.handlePagination(flags);\n\t\t\tassert.deepEqual(options, { limit: 42 });\n\t\t});\n\n\t\tit('should set limit to maximum value of 1000', function () {\n\t\t\tlet flags = { 'max-items': 420_000 };\n\t\t\tlet options = paginationUtilities.handlePagination(flags);\n\t\t\tassert.deepEqual(options, { limit: 1000 });\n\t\t});\n\n\t\tit('should throw exception if max-items is equal to 0', function () {\n\t\t\tlet flags = { 'max-items': 0 };\n\t\t\tassert.throws(\n\t\t\t\t() => paginationUtilities.handlePagination(flags),\n\t\t\t\t'Max items must be greater than 0'\n\t\t\t);\n\t\t});\n\n\t\tit('should throw exception if max-items is less than 0', function () {\n\t\t\tlet flags = { 'max-items': -100 };\n\t\t\tassert.throws(\n\t\t\t\t() => paginationUtilities.handlePagination(flags),\n\t\t\t\t'Max items must be greater than 0'\n\t\t\t);\n\t\t});\n\n\t\tit('should set default limit to 1000', function () {\n\t\t\tlet flags = {};\n\t\t\tlet options = paginationUtilities.handlePagination(flags);\n\t\t\tassert.deepEqual(options, { limit: 1000 });\n\t\t});\n\n\t\tit('should set usemarker to true', function () {\n\t\t\tlet flags = {};\n\t\t\tlet options = paginationUtilities.forceMarkerPagination(flags);\n\t\t\tassert.deepEqual(options, { usemarker: true, limit: 1000 });\n\t\t});\n\n\t\tit('flags contain max-items', function () {\n\t\t\tassert.containsAllKeys(paginationUtilities.flags, 'max-items');\n\t\t});\n\t});\n\n\tdescribe('Endpoints query parameterers', function () {\n\t\tdescribe('Pagination', function () {\n\t\t\tlet fixture = getFixture(\n\t\t\t\t\t'pagination/get_files_id_versions_marker.json'\n\t\t\t\t),\n\t\t\t\tjsonOutput = getFixture(\n\t\t\t\t\t'output/files_versions_list_pagination_json.txt'\n\t\t\t\t),\n\t\t\t\tfileId = '1234567890';\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get(`/2.0/files/${fileId}/versions`)\n\t\t\t\t\t.query({ limit: 2 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\t'files:versions',\n\t\t\t\t\tfileId,\n\t\t\t\t\t'--token=test',\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--max-items=2',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should include max-items as limit and return response',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t});\n\n\t\tdescribe('Forced marker pagination', function () {\n\t\t\tlet fixture = getFixture('pagination/get_folders_id_items_marker'),\n\t\t\t\tjsonOutput = getFixture(\n\t\t\t\t\t'output/folders_list_items_pagination_json.txt'\n\t\t\t\t),\n\t\t\t\tfolderId = '0';\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get(`/2.0/folders/${folderId}/items`)\n\t\t\t\t\t.query({ usemarker: true, limit: 2 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\t'folders:items',\n\t\t\t\t\tfolderId,\n\t\t\t\t\t'--token=test',\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--max-items=2',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should include max-items as limit, usemarker set to true and return response',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, jsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t});\n\n\t\tdescribe('Max items', function () {\n\t\t\tlet fixture = getFixture(\n\t\t\t\t\t'pagination/get_folders_id_items_marker.json'\n\t\t\t\t),\n\t\t\t\toneItemJsonOutput = getFixture(\n\t\t\t\t\t'output/folders_list_items_pagination_one_item_json.txt'\n\t\t\t\t),\n\t\t\t\ttwoItemsJsonOutput = getFixture(\n\t\t\t\t\t'output/folders_list_items_pagination_json.txt'\n\t\t\t\t),\n\t\t\t\tfolderId = '0';\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get(`/2.0/folders/${folderId}/items`)\n\t\t\t\t\t.query({ usemarker: true, limit: 1 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\t'folders:items',\n\t\t\t\t\tfolderId,\n\t\t\t\t\t'--token=test',\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--max-items=1',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should return number of items up to max-items if max-items is smaller than the result length',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, oneItemJsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\ttest.nock(TEST_API_ROOT, (api) =>\n\t\t\t\tapi\n\t\t\t\t\t.get(`/2.0/folders/${folderId}/items`)\n\t\t\t\t\t.query({ usemarker: true, limit: 3 })\n\t\t\t\t\t.reply(200, fixture)\n\t\t\t)\n\t\t\t\t.stdout()\n\t\t\t\t.command([\n\t\t\t\t\t'folders:items',\n\t\t\t\t\tfolderId,\n\t\t\t\t\t'--token=test',\n\t\t\t\t\t'--json',\n\t\t\t\t\t'--max-items=3',\n\t\t\t\t])\n\t\t\t\t.it(\n\t\t\t\t\t'should return number of items up to total number of items if max-items is greater than the result length',\n\t\t\t\t\t(context) => {\n\t\t\t\t\t\tassert.equal(context.stdout, twoItemsJsonOutput);\n\t\t\t\t\t}\n\t\t\t\t);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/pkce-support.test.js",
    "content": "'use strict';\n\nconst { assert } = require('chai');\nconst { createHash } = require('node:crypto');\nconst {\n\tMIN_PKCE_CODE_VERIFIER_LENGTH,\n\tMAX_PKCE_CODE_VERIFIER_LENGTH,\n\ttoBase64Url,\n\tgeneratePKCE,\n} = require('../src/pkce-support');\n\ndescribe('PKCE Support', function () {\n\tdescribe('toBase64Url', function () {\n\t\tit('should convert base64 into URL-safe format without padding', function () {\n\t\t\tconst result = toBase64Url(Buffer.from([251, 239, 255]));\n\t\t\tassert.equal(result, '--__');\n\t\t});\n\t});\n\n\tdescribe('generatePKCE', function () {\n\t\tit('should default verifier length to max supported value', function () {\n\t\t\tconst pkce = generatePKCE();\n\t\t\tassert.lengthOf(pkce.codeVerifier, MAX_PKCE_CODE_VERIFIER_LENGTH);\n\t\t\tassert.match(pkce.codeVerifier, /^[A-Za-z0-9_-]+$/u);\n\t\t});\n\n\t\tfor (const { name, length } of [\n\t\t\t{ name: 'min', length: MIN_PKCE_CODE_VERIFIER_LENGTH },\n\t\t\t{\n\t\t\t\tname: 'mid',\n\t\t\t\tlength: Math.floor(\n\t\t\t\t\t(MIN_PKCE_CODE_VERIFIER_LENGTH +\n\t\t\t\t\t\tMAX_PKCE_CODE_VERIFIER_LENGTH) /\n\t\t\t\t\t\t2\n\t\t\t\t),\n\t\t\t},\n\t\t\t{ name: 'max', length: MAX_PKCE_CODE_VERIFIER_LENGTH },\n\t\t]) {\n\t\t\tit(`should generate valid verifier and challenge for ${name} length`, function () {\n\t\t\t\tconst pkce = generatePKCE(length);\n\t\t\t\tassert.lengthOf(pkce.codeVerifier, length);\n\t\t\t\tassert.match(pkce.codeVerifier, /^[A-Za-z0-9_-]+$/u);\n\t\t\t\tassert.equal(\n\t\t\t\t\tpkce.codeChallenge,\n\t\t\t\t\ttoBase64Url(\n\t\t\t\t\t\tcreateHash('sha256').update(pkce.codeVerifier).digest()\n\t\t\t\t\t)\n\t\t\t\t);\n\t\t\t});\n\t\t}\n\n\t\tit('should derive codeChallenge from generated codeVerifier (S256)', function () {\n\t\t\tconst { codeVerifier, codeChallenge } = generatePKCE(64);\n\t\t\tconst expectedChallenge = toBase64Url(\n\t\t\t\tcreateHash('sha256').update(codeVerifier).digest()\n\t\t\t);\n\t\t\tassert.equal(codeChallenge, expectedChallenge);\n\t\t});\n\n\t\tfor (const { name, length } of [\n\t\t\t{ name: 'below minimum', length: 42 },\n\t\t\t{ name: 'above maximum', length: 129 },\n\t\t\t{ name: 'non-integer', length: 43.5 },\n\t\t]) {\n\t\t\tit(`should throw for ${name} verifier length`, function () {\n\t\t\t\tassert.throws(\n\t\t\t\t\t() => generatePKCE(length),\n\t\t\t\t\t/PKCE code verifier length must be an integer in range 43-128/u\n\t\t\t\t);\n\t\t\t});\n\t\t}\n\t});\n});\n"
  },
  {
    "path": "test/secure-storage.test.js",
    "content": "'use strict';\n\nconst { assert } = require('chai');\nconst sinon = require('sinon');\n\ndescribe('SecureStorage', function () {\n\tconst sandbox = sinon.createSandbox();\n\tlet secureStorage;\n\n\tafterEach(function () {\n\t\tsandbox.verifyAndRestore();\n\t\tdelete require.cache[require.resolve('../src/secure-storage')];\n\t});\n\n\tdescribe('on macOS (darwin)', function () {\n\t\tbeforeEach(function () {\n\t\t\tif (process.platform !== 'darwin') {\n\t\t\t\tthis.skip();\n\t\t\t}\n\t\t\tsecureStorage = require('../src/secure-storage');\n\t\t});\n\n\t\tit('should use keychain backend on macOS', function () {\n\t\t\tassert.equal(secureStorage.backend, 'keychain');\n\t\t\tassert.isTrue(secureStorage.available);\n\t\t});\n\n\t\tit('getPassword should delegate to keychain module', async function () {\n\t\t\tconst kc = require('keychain');\n\t\t\tconst stub = sandbox\n\t\t\t\t.stub(kc, 'getPassword')\n\t\t\t\t.callsFake((opts, fn) => fn(null, 'stored-value'));\n\n\t\t\tconst password = await secureStorage.getPassword('boxcli', 'Box');\n\n\t\t\tassert.equal(password, 'stored-value');\n\t\t\tassert.isTrue(stub.calledOnce);\n\t\t\tassert.deepEqual(stub.firstCall.args[0], {\n\t\t\t\taccount: 'Box',\n\t\t\t\tservice: 'boxcli',\n\t\t\t});\n\t\t});\n\n\t\tit('getPassword should return null when not found', async function () {\n\t\t\tconst kc = require('keychain');\n\t\t\tsandbox\n\t\t\t\t.stub(kc, 'getPassword')\n\t\t\t\t.callsFake((opts, fn) => fn(new Error('not found'), null));\n\n\t\t\tconst password = await secureStorage.getPassword('boxcli', 'Box');\n\n\t\t\tassert.isNull(password);\n\t\t});\n\n\t\tit('setPassword should delegate to keychain module', async function () {\n\t\t\tconst kc = require('keychain');\n\t\t\tconst stub = sandbox\n\t\t\t\t.stub(kc, 'setPassword')\n\t\t\t\t.callsFake((opts, fn) => fn(null));\n\n\t\t\tawait secureStorage.setPassword('boxcli', 'Box', 'secret');\n\n\t\t\tassert.isTrue(stub.calledOnce);\n\t\t\tassert.deepEqual(stub.firstCall.args[0], {\n\t\t\t\taccount: 'Box',\n\t\t\t\tservice: 'boxcli',\n\t\t\t\tpassword: 'secret',\n\t\t\t});\n\t\t});\n\n\t\tit('deletePassword should delegate to keychain module', async function () {\n\t\t\tconst kc = require('keychain');\n\t\t\tconst stub = sandbox\n\t\t\t\t.stub(kc, 'deletePassword')\n\t\t\t\t.callsFake((opts, fn) => fn(null));\n\n\t\t\tconst result = await secureStorage.deletePassword('boxcli', 'Box');\n\n\t\t\tassert.isTrue(result);\n\t\t\tassert.isTrue(stub.calledOnce);\n\t\t\tassert.deepEqual(stub.firstCall.args[0], {\n\t\t\t\taccount: 'Box',\n\t\t\t\tservice: 'boxcli',\n\t\t\t});\n\t\t});\n\n\t\tit('deletePassword should return false when not found', async function () {\n\t\t\tconst kc = require('keychain');\n\t\t\tsandbox\n\t\t\t\t.stub(kc, 'deletePassword')\n\t\t\t\t.callsFake((opts, fn) =>\n\t\t\t\t\tfn(new Error('Could not find password'))\n\t\t\t\t);\n\n\t\t\tconst result = await secureStorage.deletePassword('boxcli', 'Box');\n\n\t\t\tassert.isFalse(result);\n\t\t});\n\t});\n\n\tdescribe('availability checks', function () {\n\t\tit('should report available=true on supported platform with backend', function () {\n\t\t\tsecureStorage = require('../src/secure-storage');\n\t\t\tif (secureStorage.backend) {\n\t\t\t\tassert.isTrue(secureStorage.available);\n\t\t\t}\n\t\t});\n\n\t\tit('getPassword should return null when not available', async function () {\n\t\t\tsecureStorage = require('../src/secure-storage');\n\t\t\tsandbox.stub(secureStorage, 'available').value(false);\n\n\t\t\tconst password = await secureStorage.getPassword('boxcli', 'Box');\n\t\t\tassert.isNull(password);\n\t\t});\n\n\t\tit('setPassword should throw when not available', async function () {\n\t\t\tsecureStorage = require('../src/secure-storage');\n\t\t\tsandbox.stub(secureStorage, 'available').value(false);\n\n\t\t\ttry {\n\t\t\t\tawait secureStorage.setPassword('boxcli', 'Box', 'secret');\n\t\t\t\tassert.fail('Should have thrown');\n\t\t\t} catch (error) {\n\t\t\t\tassert.include(error.message, 'not available');\n\t\t\t}\n\t\t});\n\n\t\tit('deletePassword should return false when not available', async function () {\n\t\t\tsecureStorage = require('../src/secure-storage');\n\t\t\tsandbox.stub(secureStorage, 'available').value(false);\n\n\t\t\tconst result = await secureStorage.deletePassword('boxcli', 'Box');\n\t\t\tassert.isFalse(result);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/token-cache.test.js",
    "content": "'use strict';\n\nconst { expect } = require('chai');\nconst sinon = require('sinon');\nconst fs = require('node:fs');\nconst path = require('node:path');\nconst os = require('node:os');\n\nconst CLITokenCache = require('../src/token-cache');\nconst utilities = require('../src/util');\n\ndescribe('CLITokenCache', function () {\n\tconst testEnvName = 'test-environment';\n\tconst testTokenInfo = {\n\t\taccessToken: 'test-access-token',\n\t\taccessTokenTTLMS: 3_600_000,\n\t\trefreshToken: 'test-refresh-token',\n\t\tacquiredAtMS: Date.now(),\n\t};\n\tconst testFilePath = path.join(\n\t\tos.homedir(),\n\t\t'.box',\n\t\t`${testEnvName}_token_cache.json`\n\t);\n\n\tlet tokenCache;\n\tlet keytarStub;\n\n\tbeforeEach(function () {\n\t\ttokenCache = new CLITokenCache(testEnvName);\n\t});\n\n\tafterEach(function () {\n\t\t// Clean up any test files\n\t\tif (fs.existsSync(testFilePath)) {\n\t\t\ttry {\n\t\t\t\tfs.unlinkSync(testFilePath);\n\t\t\t} catch {\n\t\t\t\t// Ignore cleanup errors\n\t\t\t}\n\t\t}\n\n\t\t// Restore stubs\n\t\tif (keytarStub) {\n\t\t\tkeytarStub.restore();\n\t\t}\n\t});\n\n\tdescribe('constructor', function () {\n\t\tit('should initialize with environment name', function () {\n\t\t\texpect(tokenCache.environmentName).to.equal(testEnvName);\n\t\t});\n\n\t\tit('should set correct file path', function () {\n\t\t\texpect(tokenCache.filePath).to.equal(testFilePath);\n\t\t});\n\n\t\tit('should set correct secure storage service name', function () {\n\t\t\texpect(tokenCache.serviceName).to.equal(\n\t\t\t\t`boxcli-token-${testEnvName}`\n\t\t\t);\n\t\t});\n\n\t\tit('should set secure storage account name', function () {\n\t\t\texpect(tokenCache.accountName).to.equal('Box');\n\t\t});\n\n\t\tit('should detect secure storage support on supported platforms', function () {\n\t\t\tconst secureStorage = require('../src/secure-storage');\n\t\t\texpect(tokenCache.supportsSecureStorage).to.equal(\n\t\t\t\tsecureStorage.available\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe('read() - File-based storage', function () {\n\t\tit('should read token from file when secure storage not available', function (done) {\n\t\t\t// Create a test token file\n\t\t\tconst boxDir = path.join(os.homedir(), '.box');\n\t\t\tif (!fs.existsSync(boxDir)) {\n\t\t\t\tfs.mkdirSync(boxDir, { recursive: true });\n\t\t\t}\n\t\t\tfs.writeFileSync(\n\t\t\t\ttestFilePath,\n\t\t\t\tJSON.stringify(testTokenInfo),\n\t\t\t\t'utf8'\n\t\t\t);\n\n\t\t\t// Create cache instance with secure storage disabled\n\t\t\tconst cacheWithoutSecure = new CLITokenCache(testEnvName);\n\t\t\tcacheWithoutSecure.supportsSecureStorage = false;\n\n\t\t\tcacheWithoutSecure.read((error, tokenInfo) => {\n\t\t\t\texpect(error).to.be.null;\n\t\t\t\texpect(tokenInfo.accessToken).to.equal(\n\t\t\t\t\ttestTokenInfo.accessToken\n\t\t\t\t);\n\t\t\t\texpect(tokenInfo.refreshToken).to.equal(\n\t\t\t\t\ttestTokenInfo.refreshToken\n\t\t\t\t);\n\t\t\t\tdone();\n\t\t\t});\n\t\t});\n\n\t\tit('should return empty object when file does not exist', function (done) {\n\t\t\tconst cacheWithoutSecure = new CLITokenCache('nonexistent-env');\n\t\t\tcacheWithoutSecure.supportsSecureStorage = false;\n\n\t\t\tcacheWithoutSecure.read((error, tokenInfo) => {\n\t\t\t\texpect(error).to.be.null;\n\t\t\t\texpect(tokenInfo).to.be.an('object');\n\t\t\t\texpect(tokenInfo.accessToken).to.be.undefined;\n\t\t\t\tdone();\n\t\t\t});\n\t\t});\n\n\t\tit('should handle invalid JSON in file gracefully', function (done) {\n\t\t\tconst boxDir = path.join(os.homedir(), '.box');\n\t\t\tif (!fs.existsSync(boxDir)) {\n\t\t\t\tfs.mkdirSync(boxDir, { recursive: true });\n\t\t\t}\n\t\t\tfs.writeFileSync(testFilePath, 'invalid json', 'utf8');\n\n\t\t\tconst cacheWithoutSecure = new CLITokenCache(testEnvName);\n\t\t\tcacheWithoutSecure.supportsSecureStorage = false;\n\n\t\t\tcacheWithoutSecure.read((error, tokenInfo) => {\n\t\t\t\texpect(error).to.be.null;\n\t\t\t\texpect(tokenInfo).to.be.an('object');\n\t\t\t\texpect(tokenInfo.accessToken).to.be.undefined;\n\t\t\t\tdone();\n\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('write() - File-based storage', function () {\n\t\tit('should write token to file when secure storage not available', function (done) {\n\t\t\tconst cacheWithoutSecure = new CLITokenCache(testEnvName);\n\t\t\tcacheWithoutSecure.supportsSecureStorage = false;\n\n\t\t\tcacheWithoutSecure.write(testTokenInfo, (error) => {\n\t\t\t\texpect(error).to.be.undefined;\n\t\t\t\texpect(fs.existsSync(testFilePath)).to.be.true;\n\n\t\t\t\tconst fileContent = fs.readFileSync(testFilePath, 'utf8');\n\t\t\t\tconst savedToken = JSON.parse(fileContent);\n\t\t\t\texpect(savedToken.accessToken).to.equal(\n\t\t\t\t\ttestTokenInfo.accessToken\n\t\t\t\t);\n\t\t\t\tdone();\n\t\t\t});\n\t\t});\n\n\t\tit('should format JSON with proper indentation', function (done) {\n\t\t\tconst cacheWithoutSecure = new CLITokenCache(testEnvName);\n\t\t\tcacheWithoutSecure.supportsSecureStorage = false;\n\n\t\t\tcacheWithoutSecure.write(testTokenInfo, (error) => {\n\t\t\t\texpect(error).to.be.undefined;\n\n\t\t\t\tconst fileContent = fs.readFileSync(testFilePath, 'utf8');\n\t\t\t\texpect(fileContent).to.include('\\n    ');\n\t\t\t\tdone();\n\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('clear()', function () {\n\t\tit('should delete token file', function (done) {\n\t\t\tconst cacheWithoutSecure = new CLITokenCache(testEnvName);\n\t\t\tcacheWithoutSecure.supportsSecureStorage = false;\n\n\t\t\t// First write a token\n\t\t\tcacheWithoutSecure.write(testTokenInfo, () => {\n\t\t\t\texpect(fs.existsSync(testFilePath)).to.be.true;\n\n\t\t\t\t// Then clear it\n\t\t\t\tcacheWithoutSecure.clear((error) => {\n\t\t\t\t\texpect(error).to.be.undefined;\n\t\t\t\t\texpect(fs.existsSync(testFilePath)).to.be.false;\n\t\t\t\t\tdone();\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\n\t\tit('should not error when file does not exist', function (done) {\n\t\t\tconst cacheWithoutSecure = new CLITokenCache('nonexistent-env');\n\t\t\tcacheWithoutSecure.supportsSecureStorage = false;\n\n\t\t\tcacheWithoutSecure.clear((error) => {\n\t\t\t\texpect(error).to.be.undefined;\n\t\t\t\tdone();\n\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('store() - TS SDK compatible', function () {\n\t\tit('should store token in promise-based interface', async function () {\n\t\t\tconst cacheWithoutSecure = new CLITokenCache(testEnvName);\n\t\t\tcacheWithoutSecure.supportsSecureStorage = false;\n\n\t\t\tconst tsToken = {\n\t\t\t\taccessToken: 'ts-access-token',\n\t\t\t\texpiresIn: 3600,\n\t\t\t\trefreshToken: 'ts-refresh-token',\n\t\t\t};\n\n\t\t\tawait cacheWithoutSecure.store(tsToken);\n\n\t\t\tconst fileContent = fs.readFileSync(testFilePath, 'utf8');\n\t\t\tconst savedToken = JSON.parse(fileContent);\n\t\t\texpect(savedToken.accessToken).to.equal('ts-access-token');\n\t\t\texpect(savedToken.refreshToken).to.equal('ts-refresh-token');\n\t\t\texpect(savedToken.accessTokenTTLMS).to.equal(3_600_000);\n\t\t\texpect(savedToken.acquiredAtMS).to.be.a('number');\n\t\t});\n\t});\n\n\tdescribe('get() - TS SDK compatible', function () {\n\t\tit('should get token in promise-based interface', async function () {\n\t\t\tconst cacheWithoutSecure = new CLITokenCache(testEnvName);\n\t\t\tcacheWithoutSecure.supportsSecureStorage = false;\n\n\t\t\t// First write a token\n\t\t\tawait cacheWithoutSecure.store({\n\t\t\t\taccessToken: 'ts-access-token',\n\t\t\t\texpiresIn: 3600,\n\t\t\t\trefreshToken: 'ts-refresh-token',\n\t\t\t});\n\n\t\t\t// Then get it\n\t\t\tconst tokenInfo = await cacheWithoutSecure.get();\n\t\t\texpect(tokenInfo).to.not.be.undefined;\n\t\t\texpect(tokenInfo.accessToken).to.equal('ts-access-token');\n\t\t});\n\n\t\tit('should return undefined when no token exists', async function () {\n\t\t\tconst cacheWithoutSecure = new CLITokenCache('nonexistent-env');\n\t\t\tcacheWithoutSecure.supportsSecureStorage = false;\n\n\t\t\tconst tokenInfo = await cacheWithoutSecure.get();\n\t\t\texpect(tokenInfo).to.be.undefined;\n\t\t});\n\t});\n\n\tdescribe('Secure Storage - Backward Compatibility', function () {\n\t\tit('should read existing file-based token when secure storage is empty', function (done) {\n\t\t\tif (!tokenCache.supportsSecureStorage) {\n\t\t\t\tthis.skip();\n\t\t\t}\n\n\t\t\t// Create a file-based token (simulating old version)\n\t\t\tconst boxDir = path.join(os.homedir(), '.box');\n\t\t\tif (!fs.existsSync(boxDir)) {\n\t\t\t\tfs.mkdirSync(boxDir, { recursive: true });\n\t\t\t}\n\t\t\tfs.writeFileSync(\n\t\t\t\ttestFilePath,\n\t\t\t\tJSON.stringify(testTokenInfo),\n\t\t\t\t'utf8'\n\t\t\t);\n\n\t\t\ttokenCache.read((error, tokenInfo) => {\n\t\t\t\texpect(error).to.be.null;\n\t\t\t\texpect(tokenInfo.accessToken).to.equal(\n\t\t\t\t\ttestTokenInfo.accessToken\n\t\t\t\t);\n\t\t\t\texpect(fs.existsSync(testFilePath)).to.be.true; // File not deleted on read\n\t\t\t\tdone();\n\t\t\t});\n\t\t});\n\n\t\tit('should migrate file-based token to secure storage on write', function (done) {\n\t\t\tif (!tokenCache.supportsSecureStorage) {\n\t\t\t\tthis.skip();\n\t\t\t}\n\n\t\t\t// Create a file-based token\n\t\t\tconst boxDir = path.join(os.homedir(), '.box');\n\t\t\tif (!fs.existsSync(boxDir)) {\n\t\t\t\tfs.mkdirSync(boxDir, { recursive: true });\n\t\t\t}\n\t\t\tfs.writeFileSync(\n\t\t\t\ttestFilePath,\n\t\t\t\tJSON.stringify(testTokenInfo),\n\t\t\t\t'utf8'\n\t\t\t);\n\t\t\texpect(fs.existsSync(testFilePath)).to.be.true;\n\n\t\t\t// Write a new token (should migrate)\n\t\t\tconst newToken = { ...testTokenInfo, accessToken: 'new-token' };\n\t\t\ttokenCache.write(newToken, (error) => {\n\t\t\t\texpect(error).to.be.undefined;\n\n\t\t\t\t// File should be deleted after migration\n\t\t\t\tsetTimeout(() => {\n\t\t\t\t\texpect(fs.existsSync(testFilePath)).to.be.false;\n\t\t\t\t\tdone();\n\t\t\t\t}, 100);\n\t\t\t});\n\t\t});\n\t});\n\n\tdescribe('Multiple Environments', function () {\n\t\tit('should isolate tokens between different environments', function (done) {\n\t\t\tconst env1Cache = new CLITokenCache('env-1');\n\t\t\tconst env2Cache = new CLITokenCache('env-2');\n\n\t\t\tenv1Cache.supportsSecureStorage = false;\n\t\t\tenv2Cache.supportsSecureStorage = false;\n\n\t\t\tconst token1 = { ...testTokenInfo, accessToken: 'token-for-env-1' };\n\t\t\tconst token2 = { ...testTokenInfo, accessToken: 'token-for-env-2' };\n\n\t\t\t// Write tokens for both environments\n\t\t\tenv1Cache.write(token1, () => {\n\t\t\t\tenv2Cache.write(token2, () => {\n\t\t\t\t\t// Read them back\n\t\t\t\t\tenv1Cache.read((error1, tokenInfo1) => {\n\t\t\t\t\t\tenv2Cache.read((error2, tokenInfo2) => {\n\t\t\t\t\t\t\texpect(tokenInfo1.accessToken).to.equal(\n\t\t\t\t\t\t\t\t'token-for-env-1'\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t\texpect(tokenInfo2.accessToken).to.equal(\n\t\t\t\t\t\t\t\t'token-for-env-2'\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\t\t// Clean up\n\t\t\t\t\t\t\tenv1Cache.clear(() => {\n\t\t\t\t\t\t\t\tenv2Cache.clear(() => {\n\t\t\t\t\t\t\t\t\tdone();\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t});\n\t\t\t\t\t});\n\t\t\t\t});\n\t\t\t});\n\t\t});\n\n\t\tit('should use different service names for different environments', function () {\n\t\t\tconst env1Cache = new CLITokenCache('production');\n\t\t\tconst env2Cache = new CLITokenCache('development');\n\n\t\t\texpect(env1Cache.serviceName).to.equal('boxcli-token-production');\n\t\t\texpect(env2Cache.serviceName).to.equal(\n\t\t\t\t'boxcli-token-development'\n\t\t\t);\n\t\t});\n\t});\n\n\tdescribe('Error Handling', function () {\n\t\tit('should ignore missing token file when clearing', function (done) {\n\t\t\tconst cacheWithoutSecure = new CLITokenCache('missing-file-env');\n\t\t\tcacheWithoutSecure.supportsSecureStorage = false;\n\n\t\t\tconst unlinkStub = sinon.stub(utilities, 'unlinkAsync').rejects(\n\t\t\t\tObject.assign(new Error('No such file or directory'), {\n\t\t\t\t\tcode: 'ENOENT',\n\t\t\t\t})\n\t\t\t);\n\n\t\t\tcacheWithoutSecure.clear((error) => {\n\t\t\t\texpect(error).to.be.undefined;\n\t\t\t\tunlinkStub.restore();\n\t\t\t\tdone();\n\t\t\t});\n\t\t});\n\n\t\tit('should report file deletion failures when clearing', function (done) {\n\t\t\tconst cacheWithoutSecure = new CLITokenCache('delete-failure-env');\n\t\t\tcacheWithoutSecure.supportsSecureStorage = false;\n\n\t\t\tconst unlinkStub = sinon.stub(utilities, 'unlinkAsync').rejects(\n\t\t\t\tObject.assign(new Error('Permission denied'), {\n\t\t\t\t\tcode: 'EACCES',\n\t\t\t\t})\n\t\t\t);\n\n\t\t\tcacheWithoutSecure.clear((error) => {\n\t\t\t\texpect(error).to.exist;\n\t\t\t\texpect(error.message).to.equal('Failed to delete token cache');\n\t\t\t\texpect(error.cause).to.exist;\n\t\t\t\texpect(error.cause.message).to.equal(\n\t\t\t\t\t'Failed to delete token file'\n\t\t\t\t);\n\t\t\t\tunlinkStub.restore();\n\t\t\t\tdone();\n\t\t\t});\n\t\t});\n\n\t\tit('should report secure storage deletion failures when clearing', function (done) {\n\t\t\tif (!tokenCache.supportsSecureStorage) {\n\t\t\t\tthis.skip();\n\t\t\t}\n\n\t\t\tconst unlinkStub = sinon.stub(utilities, 'unlinkAsync').resolves();\n\t\t\tconst deletePasswordStub = sinon\n\t\t\t\t.stub(tokenCache.secureStorage, 'deletePassword')\n\t\t\t\t.rejects(\n\t\t\t\t\tObject.assign(new Error('Permission denied'), {\n\t\t\t\t\t\tcode: 'EACCES',\n\t\t\t\t\t})\n\t\t\t\t);\n\n\t\t\ttokenCache.clear((error) => {\n\t\t\t\texpect(error).to.exist;\n\t\t\t\texpect(error.message).to.equal('Failed to delete token cache');\n\t\t\t\texpect(error.cause).to.exist;\n\t\t\t\texpect(error.cause.message).to.equal(\n\t\t\t\t\t'Failed to delete token from secure storage'\n\t\t\t\t);\n\t\t\t\tdeletePasswordStub.restore();\n\t\t\t\tunlinkStub.restore();\n\t\t\t\tdone();\n\t\t\t});\n\t\t});\n\n\t\tit('should fallback to file storage if secure storage write fails', function (done) {\n\t\t\tif (!tokenCache.supportsSecureStorage) {\n\t\t\t\tthis.skip();\n\t\t\t}\n\n\t\t\tconst setPasswordStub = sinon\n\t\t\t\t.stub(tokenCache.secureStorage, 'setPassword')\n\t\t\t\t.rejects(new Error('Secure storage unavailable'));\n\n\t\t\ttokenCache.write(testTokenInfo, (error) => {\n\t\t\t\texpect(error).to.be.undefined;\n\t\t\t\texpect(fs.existsSync(testFilePath)).to.be.true;\n\n\t\t\t\tsetPasswordStub.restore();\n\t\t\t\tdone();\n\t\t\t});\n\t\t});\n\n\t\tit('should fallback to file storage if secure storage read fails', function (done) {\n\t\t\tif (!tokenCache.supportsSecureStorage) {\n\t\t\t\tthis.skip();\n\t\t\t}\n\n\t\t\tconst boxDir = path.join(os.homedir(), '.box');\n\t\t\tif (!fs.existsSync(boxDir)) {\n\t\t\t\tfs.mkdirSync(boxDir, { recursive: true });\n\t\t\t}\n\t\t\tfs.writeFileSync(\n\t\t\t\ttestFilePath,\n\t\t\t\tJSON.stringify(testTokenInfo),\n\t\t\t\t'utf8'\n\t\t\t);\n\n\t\t\tconst getPasswordStub = sinon\n\t\t\t\t.stub(tokenCache.secureStorage, 'getPassword')\n\t\t\t\t.rejects(new Error('Secure storage unavailable'));\n\n\t\t\ttokenCache.read((error, tokenInfo) => {\n\t\t\t\texpect(error).to.be.null;\n\t\t\t\texpect(tokenInfo.accessToken).to.equal(\n\t\t\t\t\ttestTokenInfo.accessToken\n\t\t\t\t);\n\n\t\t\t\tgetPasswordStub.restore();\n\t\t\t\tdone();\n\t\t\t});\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "test/util.test.js",
    "content": "'use strict';\n\nconst chai = require('chai');\nconst assert = require('chai').assert;\nconst mockery = require('mockery');\nconst leche = require('leche');\nconst sinon = require('sinon');\nconst process = require('node:process');\nconst fs = require('node:fs');\nconst chaiAsPromised = require('chai-as-promised');\nconst { getDriveLetter, isWin } = require('./helpers/test-helper');\n\nchai.use(chaiAsPromised);\n\ndescribe('Utilities', function () {\n\tconst MODULE_UNDER_TEST = '../src/util';\n\n\tlet sandbox = sinon.createSandbox();\n\n\tlet mockOS, cliUtilities;\n\n\tconst isWindows = isWin();\n\n\tconst driveLetter = isWindows ? getDriveLetter() : '';\n\n\tbeforeEach(function () {\n\t\tmockery.enable({\n\t\t\tuseCleanCache: true,\n\t\t\twarnOnUnregistered: false,\n\t\t});\n\n\t\tmockOS = {\n\t\t\thomedir: sandbox.stub().returns('/home/user'),\n\t\t};\n\n\t\tmockery.registerMock('node:os', mockOS);\n\n\t\tmockery.registerAllowable(MODULE_UNDER_TEST, true);\n\t\tcliUtilities = require(MODULE_UNDER_TEST);\n\t});\n\n\tafterEach(function () {\n\t\tsandbox.verifyAndRestore();\n\t\tmockery.deregisterAll();\n\t\tmockery.disable();\n\t});\n\n\tdescribe('parsePath()', function () {\n\t\tleche.withData(\n\t\t\t{\n\t\t\t\t'bare tilde': [\n\t\t\t\t\t'~',\n\t\t\t\t\t...(isWindows\n\t\t\t\t\t\t? [String.raw`${driveLetter}\\home\\user`]\n\t\t\t\t\t\t: ['/home/user']),\n\t\t\t\t],\n\t\t\t\t'subdirectory of tilde': [\n\t\t\t\t\t'~/foo/bar',\n\t\t\t\t\t...(isWindows\n\t\t\t\t\t\t? [String.raw`${driveLetter}\\home\\user\\foo\\bar`]\n\t\t\t\t\t\t: ['/home/user/foo/bar']),\n\t\t\t\t],\n\t\t\t\t'absolute path with interior tilde': [\n\t\t\t\t\t'/var/~/bar',\n\t\t\t\t\t...(isWindows\n\t\t\t\t\t\t? [String.raw`${driveLetter}\\var\\~\\bar`]\n\t\t\t\t\t\t: ['/var/~/bar']),\n\t\t\t\t],\n\t\t\t\t'relative path with interior tilde': [\n\t\t\t\t\t'./~/bar',\n\t\t\t\t\t...(isWindows\n\t\t\t\t\t\t? [String.raw`${process.cwd()}\\~\\bar`]\n\t\t\t\t\t\t: [`${process.cwd()}/~/bar`]),\n\t\t\t\t],\n\t\t\t\t'absolute path': [\n\t\t\t\t\t'/var/box/files',\n\t\t\t\t\t...(isWindows\n\t\t\t\t\t\t? [String.raw`${driveLetter}\\var\\box\\files`]\n\t\t\t\t\t\t: ['/var/box/files']),\n\t\t\t\t],\n\t\t\t\t'relative path': [\n\t\t\t\t\t'./foo',\n\t\t\t\t\t...(isWindows\n\t\t\t\t\t\t? [String.raw`${process.cwd()}\\foo`]\n\t\t\t\t\t\t: [`${process.cwd()}/foo`]),\n\t\t\t\t],\n\t\t\t\t'root directory': [\n\t\t\t\t\t'/',\n\t\t\t\t\t...(isWindows ? [`${driveLetter}\\\\`] : ['/']),\n\t\t\t\t],\n\t\t\t\t'relative path that REALLY should be the root': [\n\t\t\t\t\t'../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../..',\n\t\t\t\t\t...(isWindows ? [`${driveLetter}\\\\`] : ['/']),\n\t\t\t\t],\n\t\t\t\t'absolute file path': [\n\t\t\t\t\t'/foo/bar/doc.pdf',\n\t\t\t\t\t...(isWindows\n\t\t\t\t\t\t? [String.raw`${driveLetter}\\foo\\bar\\doc.pdf`]\n\t\t\t\t\t\t: ['/foo/bar/doc.pdf']),\n\t\t\t\t],\n\t\t\t\t'relative file path': [\n\t\t\t\t\t'./pic.jpg',\n\t\t\t\t\t...(isWindows\n\t\t\t\t\t\t? [String.raw`${process.cwd()}\\pic.jpg`]\n\t\t\t\t\t\t: [`${process.cwd()}/pic.jpg`]),\n\t\t\t\t],\n\t\t\t\t'file in current directory': [\n\t\t\t\t\t'essay.docx',\n\t\t\t\t\t...(isWindows\n\t\t\t\t\t\t? [String.raw`${process.cwd()}\\essay.docx`]\n\t\t\t\t\t\t: [`${process.cwd()}/essay.docx`]),\n\t\t\t\t],\n\t\t\t\t'relative file path that REALLY should be in the root directory':\n\t\t\t\t\t[\n\t\t\t\t\t\t'../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../../a.txt',\n\t\t\t\t\t\t...(isWindows\n\t\t\t\t\t\t\t? [String.raw`${driveLetter}\\a.txt`]\n\t\t\t\t\t\t\t: ['/a.txt']),\n\t\t\t\t\t],\n\t\t\t\t'folder name with spaces in it': [\n\t\t\t\t\t'/A/Folder/With/Spaces In It',\n\t\t\t\t\t...(isWindows\n\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\tString.raw`${driveLetter}\\A\\Folder\\With\\Spaces In It`,\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t: ['/A/Folder/With/Spaces In It']),\n\t\t\t\t],\n\t\t\t\t'file name with spaces in it': [\n\t\t\t\t\t'/home/otheruser/Secret Stuff.pdf',\n\t\t\t\t\t...(isWindows\n\t\t\t\t\t\t? [\n\t\t\t\t\t\t\t\tString.raw`${driveLetter}\\home\\otheruser\\Secret Stuff.pdf`,\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t: ['/home/otheruser/Secret Stuff.pdf']),\n\t\t\t\t],\n\t\t\t\t'absolute path to folder with trailing slash': [\n\t\t\t\t\t'/foo/bar/baz/',\n\t\t\t\t\t...(isWindows\n\t\t\t\t\t\t? [String.raw`${driveLetter}\\foo\\bar\\baz`]\n\t\t\t\t\t\t: ['/foo/bar/baz']),\n\t\t\t\t],\n\t\t\t\t'dot for current directory': ['.', process.cwd()],\n\t\t\t\t'dot with trailing slash for current directory': [\n\t\t\t\t\t'./',\n\t\t\t\t\tprocess.cwd(),\n\t\t\t\t],\n\t\t\t},\n\t\t\tfunction (path, expectedOutput) {\n\t\t\t\tit('should correctly parse to absolute path', function () {\n\t\t\t\t\tlet parsedPath = cliUtilities.parsePath(path);\n\t\t\t\t\tassert.strictEqual(parsedPath, expectedOutput);\n\t\t\t\t});\n\t\t\t}\n\t\t);\n\t});\n\n\tdescribe('parseMetadata()', function () {\n\t\tleche.withData(\n\t\t\t{\n\t\t\t\t'string value': ['foo=bar', { foo: 'bar' }],\n\t\t\t\t'string value with spaces': [\n\t\t\t\t\t'foo=bar and such',\n\t\t\t\t\t{ foo: 'bar and such' },\n\t\t\t\t],\n\t\t\t\t'string value with equal sign': ['foo=a=b=c', { foo: 'a=b=c' }],\n\t\t\t\t'string value with spaces and equal sign': [\n\t\t\t\t\t'foo=When x=2, then...',\n\t\t\t\t\t{ foo: 'When x=2, then...' },\n\t\t\t\t],\n\t\t\t\t'integer value': ['bar=#100', { bar: 100 }],\n\t\t\t\t'float value': ['bar=#98.6', { bar: 98.6 }],\n\t\t\t\t'empty array value': ['baz=[]', { baz: [] }],\n\t\t\t\t'string array values': [\n\t\t\t\t\t'baz=[foo,bar]',\n\t\t\t\t\t{\n\t\t\t\t\t\tbaz: ['foo', 'bar'],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'string array values with equals sign': [\n\t\t\t\t\t'quux=[x=2,y=5]',\n\t\t\t\t\t{\n\t\t\t\t\t\tquux: ['x=2', 'y=5'],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'string array values with escaped comma': [\n\t\t\t\t\tString.raw`quux=[comma (\\,),period (.)]`,\n\t\t\t\t\t{\n\t\t\t\t\t\tquux: ['comma (,)', 'period (.)'],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'key with escaped equal sign': [\n\t\t\t\t\tString.raw`x\\=y?=yes`,\n\t\t\t\t\t{ 'x=y?': 'yes' },\n\t\t\t\t],\n\t\t\t\t'string value with leading octothrope': [\n\t\t\t\t\t'hexColor=#ffffff',\n\t\t\t\t\t{ hexColor: '#ffffff' },\n\t\t\t\t],\n\t\t\t\t'string value with escaped leading octothorpe': [\n\t\t\t\t\tString.raw`hexColor=\\#123456`,\n\t\t\t\t\t{ hexColor: '#123456' },\n\t\t\t\t],\n\t\t\t\t'string value with escaped leading bracket': [\n\t\t\t\t\tString.raw`quux=\\[sic]`,\n\t\t\t\t\t{ quux: '[sic]' },\n\t\t\t\t],\n\t\t\t\t'array value with special characters in elements': [\n\t\t\t\t\t'blah=[#@%$,[stuff]]',\n\t\t\t\t\t{\n\t\t\t\t\t\tblah: ['#@%$', '[stuff]'],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'string value with leading literal backslash and octothorpe': [\n\t\t\t\t\tString.raw`grawlix=\\\\#*(^`,\n\t\t\t\t\t{ grawlix: String.raw`\\#*(^` },\n\t\t\t\t],\n\t\t\t\t'string value with leading literal backslash and bracket': [\n\t\t\t\t\tString.raw`grawlix=\\\\[^%$#!]`,\n\t\t\t\t\t{ grawlix: String.raw`\\[^%$#!]` },\n\t\t\t\t],\n\t\t\t\t'key with trailing backslash': [\n\t\t\t\t\tString.raw`ugh\\\\=escapes`,\n\t\t\t\t\t{ 'ugh\\\\': 'escapes' },\n\t\t\t\t],\n\t\t\t\t'string value of octothorpe': ['pound=#', { pound: '#' }],\n\t\t\t\t'string value of opening bracket': [\n\t\t\t\t\t'bracket=[',\n\t\t\t\t\t{ bracket: '[' },\n\t\t\t\t],\n\t\t\t\t'combination of many edge cases': [\n\t\t\t\t\tString.raw`x\\=y=[#fff,#333]`,\n\t\t\t\t\t{\n\t\t\t\t\t\t'x=y': ['#fff', '#333'],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'numeric value with unnecessary escape': [\n\t\t\t\t\tString.raw`foo=#3\\33`,\n\t\t\t\t\t{ foo: 333 },\n\t\t\t\t],\n\t\t\t\t'string value that looks like number': [\n\t\t\t\t\t'foo=#3cc',\n\t\t\t\t\t{ foo: '#3cc' },\n\t\t\t\t],\n\t\t\t\t'negative numeric value': ['foo=#-1', { foo: -1 }],\n\t\t\t\t'decimal numeric value without leading zero': [\n\t\t\t\t\t'bar=#.5',\n\t\t\t\t\t{ bar: 0.5 },\n\t\t\t\t],\n\t\t\t\t'negative decimal value without leading zero': [\n\t\t\t\t\t'delta=#-.5',\n\t\t\t\t\t{ delta: -0.5 },\n\t\t\t\t],\n\t\t\t\t'string value that looks like negative decimal without digits':\n\t\t\t\t\t['emoticon=#-.', { emoticon: '#-.' }],\n\t\t\t},\n\t\t\tfunction (value, expectedOutput) {\n\t\t\t\tit('should correctly parse metadata key-value pair', function () {\n\t\t\t\t\tlet parsedPair = cliUtilities.parseMetadata(value);\n\t\t\t\t\tassert.deepEqual(parsedPair, expectedOutput);\n\t\t\t\t});\n\t\t\t}\n\t\t);\n\t});\n\n\tdescribe('parseMetadataOp()', function () {\n\t\tleche.withData(\n\t\t\t{\n\t\t\t\t'path with string value': [\n\t\t\t\t\t'/foo=bar',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo',\n\t\t\t\t\t\tvalue: 'bar',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with string value with spaces': [\n\t\t\t\t\t'/foo=bar and such',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo',\n\t\t\t\t\t\tvalue: 'bar and such',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with string value with equal sign': [\n\t\t\t\t\t'/foo=a=b=c',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo',\n\t\t\t\t\t\tvalue: 'a=b=c',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with string value with spaces and equal sign': [\n\t\t\t\t\t'/foo=When x=2, then...',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo',\n\t\t\t\t\t\tvalue: 'When x=2, then...',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with integer value': [\n\t\t\t\t\t'/bar=#100',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/bar',\n\t\t\t\t\t\tvalue: 100,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with float value': [\n\t\t\t\t\t'/bar=#98.6',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/bar',\n\t\t\t\t\t\tvalue: 98.6,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with empty array value': [\n\t\t\t\t\t'/baz=[]',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/baz',\n\t\t\t\t\t\tvalue: [],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with string array values': [\n\t\t\t\t\t'/baz=[foo,bar]',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/baz',\n\t\t\t\t\t\tvalue: ['foo', 'bar'],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with string array values with equals sign': [\n\t\t\t\t\t'/quux=[x=2,y=5]',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/quux',\n\t\t\t\t\t\tvalue: ['x=2', 'y=5'],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with string array values with escaped comma': [\n\t\t\t\t\tString.raw`/quux=[comma (\\,),period (.)]`,\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/quux',\n\t\t\t\t\t\tvalue: ['comma (,)', 'period (.)'],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with escaped equal sign': [\n\t\t\t\t\tString.raw`/x\\=y?=yes`,\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/x=y?',\n\t\t\t\t\t\tvalue: 'yes',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with string value with leading octothrope': [\n\t\t\t\t\t'/hexColor=#ffffff',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/hexColor',\n\t\t\t\t\t\tvalue: '#ffffff',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with string value with escaped leading octothorpe': [\n\t\t\t\t\tString.raw`/hexColor=\\#123456`,\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/hexColor',\n\t\t\t\t\t\tvalue: '#123456',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with string value with escaped leading bracket': [\n\t\t\t\t\tString.raw`/quux=\\[sic]`,\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/quux',\n\t\t\t\t\t\tvalue: '[sic]',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with array value with special characters in elements': [\n\t\t\t\t\t'/blah=[#@%$,[stuff]]',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/blah',\n\t\t\t\t\t\tvalue: ['#@%$', '[stuff]'],\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with string value with leading literal backslash and octothorpe':\n\t\t\t\t\t[\n\t\t\t\t\t\tString.raw`/grawlix=\\\\#*(^`,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpath: '/grawlix',\n\t\t\t\t\t\t\tvalue: String.raw`\\#*(^`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t'path with string value with leading literal backslash and bracket':\n\t\t\t\t\t[\n\t\t\t\t\t\tString.raw`/grawlix=\\\\[^%$#!]`,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpath: '/grawlix',\n\t\t\t\t\t\t\tvalue: String.raw`\\[^%$#!]`,\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t'path with trailing backslash': [\n\t\t\t\t\tString.raw`/ugh\\\\=escapes`,\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/ugh\\\\',\n\t\t\t\t\t\tvalue: 'escapes',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with string value of octothorpe': [\n\t\t\t\t\t'/pound=#',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/pound',\n\t\t\t\t\t\tvalue: '#',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path string value of opening bracket': [\n\t\t\t\t\t'/bracket=[',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/bracket',\n\t\t\t\t\t\tvalue: '[',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with value, both having a combination of many edge cases':\n\t\t\t\t\t[\n\t\t\t\t\t\tString.raw`/x\\=y=[#fff,#333]`,\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpath: '/x=y',\n\t\t\t\t\t\t\tvalue: ['#fff', '#333'],\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t'path with numeric value with unnecessary escape': [\n\t\t\t\t\tString.raw`/foo=#3\\33`,\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo',\n\t\t\t\t\t\tvalue: 333,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with string value that looks like number': [\n\t\t\t\t\t'/foo=#3cc',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo',\n\t\t\t\t\t\tvalue: '#3cc',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with negative numeric value': [\n\t\t\t\t\t'/foo=#-1',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo',\n\t\t\t\t\t\tvalue: -1,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with decimal numeric value without leading zero': [\n\t\t\t\t\t'/bar=#.5',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/bar',\n\t\t\t\t\t\tvalue: 0.5,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with negative decimal value without leading zero': [\n\t\t\t\t\t'/delta=#-.5',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/delta',\n\t\t\t\t\t\tvalue: -0.5,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with string value that looks like negative decimal without digits':\n\t\t\t\t\t[\n\t\t\t\t\t\t'/emoticon=#-.',\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tpath: '/emoticon',\n\t\t\t\t\t\t\tvalue: '#-.',\n\t\t\t\t\t\t},\n\t\t\t\t\t],\n\t\t\t\t'paths from and to': [\n\t\t\t\t\t'/foo>/bar',\n\t\t\t\t\t{\n\t\t\t\t\t\tfrom: '/foo',\n\t\t\t\t\t\tpath: '/bar',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path from and to with escaped equal sign': [\n\t\t\t\t\tString.raw`/x\\=y?>/y\\=x?`,\n\t\t\t\t\t{\n\t\t\t\t\t\tfrom: '/x=y?',\n\t\t\t\t\t\tpath: '/y=x?',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'paths with escaped angle bracket': [\n\t\t\t\t\tString.raw`/x\\>y?>/y<\\=x?`,\n\t\t\t\t\t{\n\t\t\t\t\t\tfrom: '/x>y?',\n\t\t\t\t\t\tpath: '/y<=x?',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'single path': [\n\t\t\t\t\t'/foo',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'single path with escaped characters': [\n\t\t\t\t\tString.raw`/x\\>\\=y?`,\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/x>=y?',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'simple key': [\n\t\t\t\t\t'foo',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'key with string value': [\n\t\t\t\t\t'foo=bar',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo',\n\t\t\t\t\t\tvalue: 'bar',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with nested index': [\n\t\t\t\t\t'/options/0=new option',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/options/0',\n\t\t\t\t\t\tvalue: 'new option',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with nested key': [\n\t\t\t\t\t'/foo/bar=baz',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo/bar',\n\t\t\t\t\t\tvalue: 'baz',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with terminal': [\n\t\t\t\t\t'/options/-=next',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/options/-',\n\t\t\t\t\t\tvalue: 'next',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'key with subscript index': [\n\t\t\t\t\t'foo[0]=bar',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo/0',\n\t\t\t\t\t\tvalue: 'bar',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'key with subscript key': [\n\t\t\t\t\t'foo[bar]=baz',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo/bar',\n\t\t\t\t\t\tvalue: 'baz',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'key with terminal': [\n\t\t\t\t\t'foo[]=quux',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo/-',\n\t\t\t\t\t\tvalue: 'quux',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with escaped slash': [\n\t\t\t\t\tString.raw`/foo\\/bar=baz`,\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo~1bar',\n\t\t\t\t\t\tvalue: 'baz',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with tilde escape code': [\n\t\t\t\t\t'/foo~0bar=wat',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo~0bar',\n\t\t\t\t\t\tvalue: 'wat',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with slash escape code': [\n\t\t\t\t\t'/foo~1bar=huh',\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo~1bar',\n\t\t\t\t\t\tvalue: 'huh',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t'path with escaped tilde in segment': [\n\t\t\t\t\tString.raw`/foo\\~bar=ugh`,\n\t\t\t\t\t{\n\t\t\t\t\t\tpath: '/foo~0bar',\n\t\t\t\t\t\tvalue: 'ugh',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t},\n\t\t\tfunction (value, expectedOutput) {\n\t\t\t\tit('should correctly parse op input', function () {\n\t\t\t\t\tlet parsedOp = cliUtilities.parseMetadataOp(value);\n\t\t\t\t\tassert.deepEqual(parsedOp, expectedOutput);\n\t\t\t\t});\n\t\t\t}\n\t\t);\n\t});\n\n\tdescribe('secret masking helpers', function () {\n\t\tit('maskSecret() should preserve length and reveal only last 3 chars by default', function () {\n\t\t\tconst secret = 'abcdefghijklmnopqrstuvwxyz123456';\n\t\t\tconst masked = cliUtilities.maskSecret(secret);\n\n\t\t\tassert.strictEqual(masked.length, secret.length);\n\t\t\tassert.strictEqual(masked.slice(-3), '456');\n\t\t\tassert.strictEqual(\n\t\t\t\tmasked,\n\t\t\t\t`${'*'.repeat(secret.length - 3)}${secret.slice(-3)}`\n\t\t\t);\n\t\t});\n\n\t\tit('maskSecret() should fallback to default visible chars for invalid values', function () {\n\t\t\tconst secret = 'abcdef';\n\t\t\tconst masked = cliUtilities.maskSecret(secret, -1);\n\n\t\t\tassert.strictEqual(masked, '***def');\n\t\t});\n\n\t\tit('maskObjectValuesByKey() should mask clientSecret recursively by default', function () {\n\t\t\tconst input = {\n\t\t\t\tname: 'dev',\n\t\t\t\tclientSecret: '1234567890',\n\t\t\t\tnested: {\n\t\t\t\t\tclientSecret: 'abcdefghij',\n\t\t\t\t},\n\t\t\t\titems: [\n\t\t\t\t\t{\n\t\t\t\t\t\tclientSecret: 'qwertyuiop',\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\tother: 'value',\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t};\n\n\t\t\tconst masked = cliUtilities.maskObjectValuesByKey(input);\n\n\t\t\tassert.strictEqual(input.clientSecret, '1234567890');\n\t\t\tassert.strictEqual(masked.clientSecret, '*******890');\n\t\t\tassert.strictEqual(input.nested.clientSecret, 'abcdefghij');\n\t\t\tassert.strictEqual(masked.nested.clientSecret, '*******hij');\n\t\t\tassert.strictEqual(input.items[0].clientSecret, 'qwertyuiop');\n\t\t\tassert.strictEqual(masked.items[0].clientSecret, '*******iop');\n\t\t\tassert.strictEqual(masked.items[1].other, 'value');\n\t\t\n\t\t});\n\n\t\tit('maskObjectValuesByKey() should support custom key and visible chars', function () {\n\t\t\tconst input = {\n\t\t\t\ttoken: 'abcd1234',\n\t\t\t\tnested: {\n\t\t\t\t\ttoken: 'wxyz9876',\n\t\t\t\t},\n\t\t\t\tclientSecret: 'dont-mask-default-key-if-custom-is-used',\n\t\t\t};\n\n\t\t\tconst masked = cliUtilities.maskObjectValuesByKey(input, 'token', 2);\n\n\t\t\tassert.strictEqual(input.token, 'abcd1234');\n\t\t\tassert.strictEqual(masked.token, '******34');\n\t\t\tassert.strictEqual(input.nested.token, 'wxyz9876');\n\t\t\tassert.strictEqual(masked.nested.token, '******76');\n\t\t\tassert.strictEqual(input.clientSecret, 'dont-mask-default-key-if-custom-is-used');\n\t\t\tassert.strictEqual(masked.clientSecret,'dont-mask-default-key-if-custom-is-used');\n\t\t});\n\t});\n\n\tdescribe('checkDir()', function () {\n\t\tit('should create directory if create flag is true', async function () {\n\t\t\tconst destination = `${process.cwd()}/temp`;\n\t\t\tawait cliUtilities.checkDir(destination, true);\n\t\t\tassert.isTrue(fs.existsSync(destination));\n\t\t\tfs.rmdirSync(destination);\n\t\t});\n\n\t\tit('should create nested directory if create flag is true', async function () {\n\t\t\tconst destination = `${process.cwd()}/nestedTemp`;\n\t\t\tconst nestedDestination = `${destination}/temp`;\n\t\t\tawait cliUtilities.checkDir(nestedDestination, true);\n\t\t\tassert.isTrue(fs.existsSync(nestedDestination));\n\t\t\tfs.rmdirSync(nestedDestination);\n\t\t\tfs.rmdirSync(destination);\n\t\t});\n\n\t\tit('should throw expection if directory does not exist and create flag is false', function () {\n\t\t\tconst destination = `${process.cwd()}/nonExistingPath`;\n\t\t\tconst retrieveException = async () => {\n\t\t\t\tawait cliUtilities.checkDir(destination, false);\n\t\t\t};\n\t\t\treturn assert.isRejected(retrieveException(), Error);\n\t\t});\n\t});\n});\n"
  },
  {
    "path": "tsconfig.esm.json",
    "content": "{\n    \"compilerOptions\": {\n        \"allowJs\": true,\n        \"declaration\": true,\n        \"module\": \"Node16\",\n        \"outDir\": \"dist\",\n        \"rootDir\": \"src\",\n        \"strict\": true,\n        \"target\": \"es2022\",\n        \"moduleResolution\": \"node16\"\n    },\n    \"include\": [\"./src/**/*\"],\n    \"ts-node\": {\n        \"esm\": true\n    }\n}\n"
  }
]