diff --git a/.eslintignore b/.eslintignore new file mode 100644 index 0000000..ce76cf8 --- /dev/null +++ b/.eslintignore @@ -0,0 +1,3 @@ +lib/ +dist/ +coverage/ diff --git a/.eslintrc b/.eslintrc new file mode 100644 index 0000000..c5f4106 --- /dev/null +++ b/.eslintrc @@ -0,0 +1,15 @@ +{ + "extends": [ + "@commercelayer/eslint-config-ts" + ], + "ignorePatterns": ["test/**/*.ts", "gen/**/*.ts", "specs/**/*.ts", "*.config.js"], + "rules": { + "prettier/prettier": "off", + "@typescript-eslint/prefer-nullish-coalescing": "off", + "@typescript-eslint/strict-boolean-expressions": "off", + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/restrict-template-expressions": "off", + "@typescript-eslint/consistent-type-definitions": "off", + "@typescript-eslint/return-await": "off" + } +} diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000..3b537c2 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,60 @@ + +name: "CodeQL" + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + schedule: + - cron: '43 18 * * 4' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'javascript' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python' ] + # Learn more: + # https://docs.github.com/en/free-pro-team@latest/github/finding-security-vulnerabilities-and-errors-in-your-code/configuring-code-scanning#changing-the-languages-that-are-analyzed + + steps: + - name: Checkout repository + uses: actions/checkout@v2 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v1 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + # queries: ./path/to/local/query, your-org/your-repo/queries@main + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v1 + + # ℹ️ Command-line programs to run using the OS shell. + # 📚 https://git.io/JvXDl + + # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines + # and modify them (or add more) to build your code if your project + # uses a compiled language + + #- run: | + # make bootstrap + # make release + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v1 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 0000000..0d914b9 --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,56 @@ +name: Publish +on: + release: + types: [ published ] +jobs: + publish: + name: Publish + runs-on: ubuntu-latest + steps: + - name: Post to a Slack channel + id: slack + uses: slackapi/slack-github-action@v1 + with: + payload: | + { + "text": "New release ${{github.ref_name}} for ${{github.event.repository.name}}.", + "blocks": [ + { + "type": "section", + "text": { + "type": "mrkdwn", + "text": "New release for <${{github.event.repository.html_url}}|`${{github.event.repository.name}}`>\n*<${{github.event.release.html_url}}|release notes>*" + } + }, + { + "type": "section", + "fields": [ + { + "type": "mrkdwn", + "text": "*Project:*\n${{github.event.repository.name}}" + }, + { + "type": "mrkdwn", + "text": "*Version:*\n${{github.ref_name}}" + } + ] + }, + { + "type": "context", + "elements": [ + { + "type": "image", + "image_url": "${{github.event.sender.avatar_url}}", + "alt_text": "${{github.event.sender.login}}" + }, + { + "type": "mrkdwn", + "text": "*${{github.event.sender.login}}* has triggered this release." + } + ] + } + ] + } + env: + SLACK_WEBHOOK_URL: ${{ secrets.PIPELINE_SLACK_CHANNEL_WEBHOOK_URL }} + SLACK_WEBHOOK_TYPE: INCOMING_WEBHOOK diff --git a/.github/workflows/semantic-release.yml b/.github/workflows/semantic-release.yml new file mode 100644 index 0000000..db884fd --- /dev/null +++ b/.github/workflows/semantic-release.yml @@ -0,0 +1,40 @@ +name: Release +on: + push: + branches: [ main, beta ] + pull_request: + branches: [ main ] +jobs: + release: + name: Release + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v3 + with: + fetch-depth: 0 + persist-credentials: false + - name: Install pnpm + uses: pnpm/action-setup@v2 + with: + version: latest + - name: Setup Node.js + uses: actions/setup-node@v3 + with: + node-version: 'lts/*' + cache: 'pnpm' + - name: Install dependencies + run: pnpm install --frozen-lockfile + - name: Build package + run: pnpm build + - name: Run specs + env: + CL_SDK_DOMAIN: commercelayer.co + CL_SDK_CLIENT_ID: P1GMFxhvca4CqYtBeAKb_E4LUVEbp9bCGMP8ZiHlZo8 + CL_SDK_CLIENT_SECRET: 3xMxL0giBfoxl02TbGrNYeYl5KCmq2TdF71P05BWQzk + run: pnpm test + - name: Release + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + NPM_TOKEN: ${{ secrets.NPM_TOKEN }} + run: pnpx semantic-release diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..39efbb6 --- /dev/null +++ b/.gitignore @@ -0,0 +1,166 @@ +build/ +dist/ + + +# Created by https://www.toptal.com/developers/gitignore/api/node,macos +# Edit at https://www.toptal.com/developers/gitignore?templates=node,macos + +### macOS ### +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +### Node ### +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# TypeScript v1 declaration files +typings/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env +.env.test +.env*.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next + +# Nuxt.js build / generate output +.nuxt +dist +lib + +# Storybook build outputs +.out +.storybook-out +storybook-static + +# rollup.js default build output +dist/ + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# Temporary folders +tmp/ +temp/ + +# End of https://www.toptal.com/developers/gitignore/api/node,macos +test.ts +yarn.lock diff --git a/.markdownlint.json b/.markdownlint.json new file mode 100644 index 0000000..82e2329 --- /dev/null +++ b/.markdownlint.json @@ -0,0 +1,14 @@ +{ + "default": true, + "MD001": false, + "MD012": false, + "MD013": { + "line_length": 1000 + }, + "MD024": { + "siblings_only": true + }, + "MD025": false, + "MD033": false, + "MD041": false +} \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..0b853a4 --- /dev/null +++ b/.npmignore @@ -0,0 +1,12 @@ +build/ +gen/ +src/ +node_modules/ + +tsconfig.json +tsconfig.*.json +tslint.json +.prettierrc + +**/*.zip +**/*.log \ No newline at end of file diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..3369ecf --- /dev/null +++ b/.npmrc @@ -0,0 +1,5 @@ + +auto-install-peers=true +#strict-peer-dependencies=false + +#registry=http://localhost:4873 \ No newline at end of file diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..a718d76 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,6 @@ +{ + "semi": false, + "trailingComma": "none", + "singleQuote": true, + "printWidth": 150 +} \ No newline at end of file diff --git a/.releaserc b/.releaserc new file mode 100644 index 0000000..16bfd7c --- /dev/null +++ b/.releaserc @@ -0,0 +1,22 @@ +{ + "ci": true, + "dryRun": false, + "branches": [ + { "name": "main", "channel": "latest" }, + "+([0-9])?(.{+([0-9]),x}).x", + { "name": "beta", "prerelease": true } + ], + "plugins": [ + "@semantic-release/commit-analyzer", + "@semantic-release/release-notes-generator", + "@semantic-release/github", + "@semantic-release/npm", + ["@semantic-release/changelog", { + "changelogFile": "CHANGELOG.md" + }], + ["@semantic-release/git", { + "assets": [ "package.json", "CHANGELOG.md" ], + "message": "chore(release): ${nextRelease.version} [skip ci]\n\n${nextRelease.notes}" + }] + ] +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..c3c21d2 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,83 @@ +# [1.0.0-beta.11](https://github.com/commercelayer/provisioning-sdk/compare/v1.0.0-beta.10...v1.0.0-beta.11) (2024-01-10) + + +### Bug Fixes + +* update dependencies and fix lint errors ([8e39135](https://github.com/commercelayer/provisioning-sdk/commit/8e3913557a272b3b31d168b3c54ced26128ed7c3)) + +# [1.0.0-beta.10](https://github.com/commercelayer/provisioning-sdk/compare/v1.0.0-beta.9...v1.0.0-beta.10) (2023-12-20) + + +### Bug Fixes + +* fix singleton patch with body id ([e923c9c](https://github.com/commercelayer/provisioning-sdk/commit/e923c9ce69f5b5ea43698bd1df67f26783010d1e)) + +# [1.0.0-beta.9](https://github.com/commercelayer/provisioning-sdk/compare/v1.0.0-beta.8...v1.0.0-beta.9) (2023-12-20) + + +### Features + +* add singletons functions to client instance ([ca338e6](https://github.com/commercelayer/provisioning-sdk/commit/ca338e63574b1c0aa8301d2de2676b4e32e991cd)) +* add singletons list and functions ([5f5d4f1](https://github.com/commercelayer/provisioning-sdk/commit/5f5d4f1c8be9ae70db4765bc8e6f519597db7b17)) + +# [1.0.0-beta.8](https://github.com/commercelayer/provisioning-sdk/compare/v1.0.0-beta.7...v1.0.0-beta.8) (2023-12-20) + + +### Bug Fixes + +* fix singleton spec ([5c617a8](https://github.com/commercelayer/provisioning-sdk/commit/5c617a8af5c7682a38e645cf86607214c4cbd1de)) + + +### Features + +* add singleton update ([71e0e7b](https://github.com/commercelayer/provisioning-sdk/commit/71e0e7b3a10ec3210da8363ccb5bc9986a4673a1)) + +# [1.0.0-beta.7](https://github.com/commercelayer/provisioning-sdk/compare/v1.0.0-beta.6...v1.0.0-beta.7) (2023-12-13) + + +### Features + +* add auto generation of special actions ([08cd9ff](https://github.com/commercelayer/provisioning-sdk/commit/08cd9ffdae53c80d7b52f841c2da319488a9ee85)) + +# [1.0.0-beta.6](https://github.com/commercelayer/provisioning-sdk/compare/v1.0.0-beta.5...v1.0.0-beta.6) (2023-12-12) + + +### Bug Fixes + +* fix custom user agent option ([75f5f97](https://github.com/commercelayer/provisioning-sdk/commit/75f5f97e3dade5dd43905deba81f6c4ed46ca21b)) + +# [1.0.0-beta.5](https://github.com/commercelayer/provisioning-sdk/compare/v1.0.0-beta.4...v1.0.0-beta.5) (2023-12-07) + + +### Bug Fixes + +* singleton import ([9578382](https://github.com/commercelayer/provisioning-sdk/commit/9578382b671629d4891e77f39658ab66828eb357)) +* update schema ([9e569c7](https://github.com/commercelayer/provisioning-sdk/commit/9e569c7484896ea666f5f8079ee0833ed9dc87aa)) + +# [1.0.0-beta.4](https://github.com/commercelayer/provisioning-sdk/compare/v1.0.0-beta.3...v1.0.0-beta.4) (2023-11-30) + + +### Bug Fixes + +* release script ([006a747](https://github.com/commercelayer/provisioning-sdk/commit/006a74784c4f2fe302d4d4b0b96673df0067f8a1)) + +# [1.0.0-beta.3](https://github.com/commercelayer/provisioning-sdk/compare/v1.0.0-beta.2...v1.0.0-beta.3) (2023-11-30) + + +### Features + +* add custom user agent ([fe2050d](https://github.com/commercelayer/provisioning-sdk/commit/fe2050d4088adbdce4d8e30d6773ebf3fef28e3e)) + +# [1.0.0-beta.2](https://github.com/commercelayer/provisioning-sdk/compare/v1.0.0-beta.1...v1.0.0-beta.2) (2023-10-31) + + +### Bug Fixes + +* **doc:** fix readme ([50bf2b6](https://github.com/commercelayer/provisioning-sdk/commit/50bf2b6debd921e1ca4936ac5acc669b191116ac)) + +# 1.0.0-beta.1 (2023-10-31) + + +### Features + +* first commit of provisioning sdk ([b067f12](https://github.com/commercelayer/provisioning-sdk/commit/b067f123ed9f2e0fce53673306b05fcf479c17f0)) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..3b4d2b3 --- /dev/null +++ b/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) [2023] [Commerce Layer] + +Permission 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: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE 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. diff --git a/README.md b/README.md index decbac3..a050220 100644 --- a/README.md +++ b/README.md @@ -1 +1,396 @@ -# provisioning-sdk \ No newline at end of file +# Commerce Layer Provisioning SDK + +[![Version](https://img.shields.io/npm/v/@commercelayer/provisioning-sdk.svg)](https://npmjs.org/package/@commercelayer/provisioning-sdk) +[![Downloads/week](https://img.shields.io/npm/dw/@commercelayer/provisioning-sdk.svg)](https://npmjs.org/package/@commercelayer/provisioning-sdk) +[![License](https://img.shields.io/npm/l/@commercelayer/provisioning-sdk.svg)](https://github.com/commercelayer/commercelayer-sdk/blob/master/package.json) +[![semantic-release: angular](https://img.shields.io/badge/semantic--release-angular-e10079?logo=semantic-release)](https://github.com/semantic-release/semantic-release) +[![Release](https://github.com/commercelayer/commercelayer-sdk/actions/workflows/semantic-release.yml/badge.svg)](https://github.com/commercelayer/commercelayer-sdk/actions/workflows/semantic-release.yml) +[![CodeQL](https://github.com/commercelayer/commercelayer-cli/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/commercelayer/commercelayer-cli/actions/workflows/codeql-analysis.yml) +[![TypeScript](https://img.shields.io/badge/%3C%2F%3E-TypeScript%205-%230074c1.svg)](https://www.typescriptlang.org/) + +A JavaScript Library wrapper that makes it quick and easy to interact with the [Commerce Layer Provisioning API](https://docs.commercelayer.io/provisioning). + +## Table of contents + +- [Getting started](#getting-started) +- [Installation](#installation) +- [Authentication](#authentication) +- [Import](#import) +- [SDK usage](#sdk-usage) +- [Overriding credentials](#overriding-credentials) +- [Handling validation errors](#handling-validation-errors) +- [Contributors guide](#contributors-guide) +- [Need help?](#need-help) +- [License](#license) + +--- + +## Getting started + +To get started with Commerce Layer Provisioning SDK you need to install it, get the credentials that will allow you to perform your API calls, and import the SDK into your application's code. The sections below explain how to achieve this. + +### Installation + +Commerce Layer Provisioning SDK is available as an [npm](https://www.npmjs.com/package/@commercelayer/provisioning-sdk) and [yarn](https://yarnpkg.com/package/@commercelayer/provisioning-sdk) package that you can install with the command below: + +```shell +npm install @commercelayer/provisioning-sdk + +// or + +yarn add @commercelayer/provisioning-sdk +``` + +### Authentication + +All requests to Commerce Layer API must be authenticated with an [OAuth2](https://oauth.net/2) bearer token. Hence, before starting to use this SDK you need to get a valid access token. Kindly check [our documentation](https://docs.commercelayer.io/provisioning/authentication) for more information about the available authorization flows. + +> Feel free to use [Commerce Layer Provisioning Auth](https://github.com/commercelayer/commercelayer-js-auth), a JavaScript library that helps you wrap our authentication API. + +### Import + +You can use the ES6 default import with the SDK like so: + +```javascript +import CommerceLayerProvisioning from '@commercelayer/provisioning-sdk' + +const clp = CommerceLayerProvisioning({ + accessToken: 'your-access-token' +}) +``` + +## SDK usage + +The JavaScript SDK is a wrapper around Commerce Layer Provisioning API which means you would still be making API requests but with a different syntax. For now, we don't have comprehensive SDK documentation for every single resource our API supports, hence you will need to rely on our comprehensive [Provisioning API Reference](https://docs.commercelayer.io/provisioning/v/api-reference-p) as you go about using this SDK. So for example, if you want to create a role, take a look at the [Role object](https://docs.commercelayer.io/provisioning/v/api-reference-p/role/object) or the [Create a role](https://docs.commercelayer.io/provisioning/v/api-reference-p/roles/create) documentation to see the required attributes and/or relationships. The same goes for every other supported resource. + +The code snippets below show how to use the SDK when performing the standard CRUD operations provided by our REST API. Kindly check our [Provisioning API reference](https://docs.commercelayer.io/provisioning/v/api-reference-p) for the complete list of available **resources** and their **attributes**. + +### Create + +
+How to create a Role +
+ +```javascript + // Select the organization (it's a required relationship for the SKU resource) + const organizations = await clp.organizations.list({ filters: { name_eq: 'Test Org' } }) + + const attributes = { + name: 'Test Role', + organization: clp.organizations.relationship(organizations.first().id), // assigns the relationship + } + + const newRole = await clp.roles.create(attributes) +``` + +ℹ️ Check our API reference for more information on how to [create a Role](https://docs.commercelayer.io/provisioning/v/api-reference-p/roles/create). +
+ +### Retrieve / List + +
+How to fetch a single organization +
+ +```javascript + // Fetch the organization by ID + const org = await clp.organizations.retrieve('BxAkSVqKEn') + + // Fetch all organizations and filter by name + const orgs = await clp.organizations.list({ filters: { name_start: 'TestOrg_' } }) + + // Fetch the first organization of the list + const org = (await clp.organizations.list()).first() + + // Fetch the last organization of the list + const org = (await clp.organizations.list()).last() +``` + +ℹ️ Check our API reference for more information on how to [retrieve an organization](https://docs.commercelayer.io/provisioning/v/api-reference-p/organizations/retrieve). +
+ +
+How to fetch a collection of organizations +
+ +```javascript + // Fetch all the organizations + const orgs = await clp.organizations.list() +``` + +When fetching a collection of resources you can leverage the `meta` attribute to get its `meta` information like so: + +```javascript + const orgs = await clp.organizations.list() + const meta = orgs.meta +``` + +ℹ️ Check our API reference for more information on how to [list all SKUs](https://docs.commercelayer.io/provisioning/v/api-reference-p/organizations/list). +
+ +
+How to fetch a collection of organizations and sort the results +
+ +```javascript + // Sort the results by creation date in ascending order (default) + const orgs = await clp.organizations.list({ sort: { created_at: 'asc' } }) + + // Sort the results by creation date in descending order + const orgs = await clp.organizations.list({ sort: { created_at: 'desc' } }) + ``` + +ℹ️ Check our API reference for more information on how to [sort results](https://docs.commercelayer.io/provisioning/sorting-results). +
+ +
+How to fetch a collection of Memberships and include associations +
+ +```javascript + // Include an association (organization) + const mships = await clp.memberships.list({ include: [ 'organization' ] }) + + // Include an association (stock role) + const mships = await clp.memberships.list({ include: [ 'role' ] }) + ``` + +ℹ️ Check our API reference for more information on how to [include associations](https://docs.commercelayer.io/provisioning/including-associations). +
+ +
+How to fetch a collection of Permissions and return specific fields (sparse fieldsets) +
+ +```javascript + // Request the API to return only specific fields + const perms = await clp.permissions.list({ fields: { permissions: [ 'can_create', 'can_update' ] } }) + + // Request the API to return only specific fields of the included resource + const mships = await clp.memberships.list({ include: [ 'organization' ], fields: { organizations: [ 'name' ] } }) + ``` + +ℹ️ Check our API reference for more information on how to [use sparse fieldsets](https://docs.commercelayer.io/provisioning/sparse-fieldsets). +
+ +
+How to fetch a collection of organizations and filter data +
+ +```javascript + // Filter all the organizations fetching only the ones whose name starts with the string "ORG" + const orgs = await clp.organizations .list({ filters: { name_start: 'ORG' } }) + + // Filter all the organizations fetching only the ones whose name ends with the string "Brand" + const orgs = await clp.organizations.list({ filters: { name_end: 'Brand' } }) + + // Filter all the organizations fetching only the ones whose name contains the string "Test" + const orgs = await clp.organizations.list({ filters: { name_cont: 'Test' } }) + + // Filter all the organizations fetching only the ones created between two specific dates + // (filters combined according to the AND logic) + const orgs = await clp.organizations.list({ filters: { created_at_gt: '2018-01-01', created_at_lt: '2018-01-31'} }) + + // Filters all the organizations fetching only the ones created or updated after a specific date + // (attributes combined according to the OR logic) + const orgs = await clp.organizations.list({ filters: { updated_at_or_created_at_gt: '2019-10-10' } }) + + // Filters all the Roles fetching only the ones whose name contains the string "Admin" + // and whose organization name starts with the string "ORG" + const roles = await clp.roles.list({ filters: { name_cont: 'Admin', organization_name_start: 'ORG'} }) + ``` + +ℹ️ Check our API reference for more information on how to [filter data](https://docs.commercelayer.io/provisioning/filtering-data). +
+ +
+How to paginate a collection of organizations +
+ +When you fetch a collection of resources, you get paginated results. You can request specific pages or items in a page like so: + +```javascript + // Fetch the organizations, setting the page number to 3 and the page size to 5 + const skorgsus = await clp.organizations.list({ pageNumber: 3, pageSize: 5 }) + + // Get the total number of organizations in the collection + const orgCount = orgs.meta.recordCount + + // Get the total number of pages + const pageCount = orgs.meta.pageCount +``` + +> PS: the default page number is **1**, the default page size is **10**, and the maximum page size allowed is **25**. + +ℹ️ Check our API reference for more information on how [pagination](https://docs.commercelayer.io/provisioning/pagination) works. +
+ +
+How to iterate through a collection of Organizations +
+ +To execute a function for every item of a collection, use the `map()` method like so: + +```javascript + // Fetch the whole list of organizations (1st page) and print their ids and names to console + const orgs = await clp.organizations.list() + orgs.map(o => console.log('ID: ' + o.id + ' - Name: ' + o.name)) +``` + +
+ + + +
+How to fetch resource relationships +
+ +Many resources have relationships with other resources and instead of including these associations as seen above, you can fetch them directly. This way, in the case of 1-to-N relationships, you can filter or sort the resulting collection as standard resources. + +```javascript +// Fetch 1-to-1 related resource: billing address of an order +const org = clp.memberships.organization('xYZkjABcde') + +// Fetch 1-to-N related resources: orders associated to a customer +const perms = clp.roles.permissions('XyzKjAbCDe', { fields: ['can_create', 'can_update'] }) +``` + +In general: + +- An API endpoint like `/api/organizations` or `/api/organization/` translates to `clp.organizations` or `clp.organizations('')` with the SDK. +- 1-to-1 relationship API endpoints like `/api/roles//organization` translates to `clp.roles('', { include: ['organization'] }}` with the SDK. +- 1-to-N relationship API endpoints like `/api/roles/?include=versions` or `/api/roles//permissions` translates to `clp.roles.retrieve('', { include: ['versions'] })` or `clp.roles.permissions('')` with the SDK. + +ℹ️ Check our API reference for more information on how to [fetch relationships](https://docs.commercelayer.io/provisioning/fetching-relationships). +
+ +
+How to count resources +
+ +Many times you simply need to count how many resources exist with +certain characteristics. You can then call the special `count` +function passing a filter to get as result the total number of +resources. + +```javascript +// Get the total number of sales_channel credentials +const credentials = clp.api_credentials.count({ filters: { kind_eq: 'sales_channel' } }) + +``` + +
+ +### Update + +
+How to update an existing organization +
+ +```javascript + const org = { + id: 'xYZkjABcde', + reference: '', + reference_origin: '' + } + + clp.organizations.update(org) // updates the SKU on the server +``` + +ℹ️ Check our API reference for more information on how to [update an organization](https://docs.commercelayer.io/provisioning/v/api-reference-p/organizations/update). +
+ +### Delete + +
+How to delete an existing membership +
+ +```javascript + clp.memberships.delete('xYZkjABcde') // persisted deletion +``` + +ℹ️ Check our API reference for more information on how to [delete a membership](https://docs.commercelayer.io/provisioning/v/api-reference-p/memberships/delete). +
+ +## Overriding credentials + +If needed, Commerce Layer Provisioning SDK lets you change the client configuration and set it at a request level. To do that, just use the `config()` method or pass the `options` parameter and authenticate the API call with the desired credentials: + +```javascript + // Permanently change configuration at client level + clp.config({ accessToken: 'your-access-token' }) + const roles = await clp.roles.list() + + or + + // Use configuration at request level + clp.roles.list({}, { accessToken: 'your-access-token' }) +``` + +## Handling validation errors + +Commerce Layer Provisioning API returns specific errors (with extra information) on each attribute of a single resource. You can inspect them to properly handle validation errors (if any). To do that, use the `errors` attribute of the catched error: + +```javascript + // Log error messages to console: + const attributes = { name: '' } + + const newRole = await clp.roles.create(attributes).catch(error => console.log(error.errors)) + + // Logged errors + /* + [ + { + title: "can't be blank", + detail: "name - can't be blank", + code: 'VALIDATION_ERROR', + source: { pointer: '/data/attributes/name' }, + status: '422', + meta: { error: 'blank' } + }, + { + title: "can't be blank", + detail: "organization - can't be blank", + code: 'VALIDATION_ERROR', + source: { pointer: '/data/relationships/organization' }, + status: '422', + meta: { error: 'blank' } + } + ] + */ + +``` + +ℹ️ Check our API reference for more information about the [errors](https://docs.commercelayer.io/provisioning/handling-errors) returned by the API. + +## Contributors guide + +1. Fork [this repository](https://github.com/commercelayer/provisioning-sdk) (learn how to do this [here](https://help.github.com/articles/fork-a-repo)). + +2. Clone the forked repository like so: + + ```shell + git clone https://github.com//provisioning-sdk.git && cd provisioning-sdk + ``` + +3. Make your changes and create a pull request ([learn how to do this](https://docs.github.com/en/github/collaborating-with-issues-and-pull-requests/creating-a-pull-request)). + +4. Someone will attend to your pull request and provide some feedback. + +## Need help? + +1. Join [Commerce Layer's Slack community](https://slack.commercelayer.app). + +2. Create an [issue](https://github.com/commercelayer/provisioning-sdk/issues) in this repository. + +3. Ping us [on Twitter](https://twitter.com/commercelayer). + +## License + +This repository is published under the [MIT](LICENSE) license. diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000..1d7941d --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,13 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| ------- | ------------------ | +| 1.x.x | :white_check_mark: | +| < 1.0.0 | :x: | + +## Reporting a Vulnerability + +Please report (suspected) security vulnerabilities to . +You will receive a response from us and if the issue is confirmed, we will release patch as soon as possible depending on complexity. diff --git a/babel.config.js b/babel.config.js new file mode 100644 index 0000000..eb5877d --- /dev/null +++ b/babel.config.js @@ -0,0 +1,4 @@ +/* global module */ +module.exports = { + presets: [['@babel/preset-env', { targets: { node: 'current' } }], '@babel/preset-typescript'] +} diff --git a/gen/fixer.ts b/gen/fixer.ts new file mode 100644 index 0000000..9f5c500 --- /dev/null +++ b/gen/fixer.ts @@ -0,0 +1,49 @@ +/* eslint-disable no-console */ +import { ApiSchema } from './schema' +import { sortObjectFields } from '../src/util' +import { inspect } from 'util' + + + +const fixRedundantComponents = (schema: ApiSchema): ApiSchema => { + + const fixResMatcher = /(ResponseList|ResponseCreated|ResponseUpdated|Response)$/ + + Object.values(schema.resources).forEach(res => { + + // Remove redundant components and replace them with global resource component + Object.values(res.operations).forEach(op => { + if (op.responseType && (fixResMatcher.test(op.responseType))) { + const rt = op.responseType.replace(fixResMatcher, '') + if (res.components[op.responseType]) delete res.components[op.responseType] + if (!res.components[rt]) res.components[rt] = schema.components[rt] + op.responseType = rt + } + }) + + // Remove potential redundant operation components + Object.keys(res.components).forEach(key => { + if (fixResMatcher.test(key)) delete res.components[key] + }) + + // Sort components + res.components = sortObjectFields(res.components) + + }) + + console.log('Redundant components have been replaced') + + return schema + +} + + +const fixSchema = (schema: ApiSchema): ApiSchema => { + console.log('Fixing parsed schema...') + const fixedSchema = fixRedundantComponents(schema) + console.log('Schema fixed.') + return fixedSchema +} + + +export default fixSchema diff --git a/gen/generator.ts b/gen/generator.ts new file mode 100644 index 0000000..00d422b --- /dev/null +++ b/gen/generator.ts @@ -0,0 +1,838 @@ + +import apiSchema, { Resource, Operation, Component, Cardinality, Attribute, isObjectType } from './schema' +import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, rmSync } from 'fs' +import { basename } from 'path' +import { snakeCase } from 'lodash' +import fixSchema from './fixer' + + +/**** SDK source code generator settings ****/ +const CONFIG = { + RELATIONSHIP_FUNCTIONS: true, + TRIGGER_FUNCTIONS: true, + ACTION_FUNCTIONS: true +} +/**** **** **** **** **** **** **** **** ****/ + + +const Inflector = require('inflector-js') + + +type OperationType = 'retrieve' | 'list' | 'create' | 'update' | 'delete' + +type ApiRes = { + type: string + apiClass: string + models: Array + singleton: boolean + operations: Array + taggable: boolean + versionable: boolean +} + + +const templates: { [key: string]: string } = {} + +const global: { + version?: string + singletons: Record +} = { singletons: {} } + + + +const loadTemplates = (): void => { + const tplDir = './gen/templates' + const tplList = readdirSync(tplDir, { encoding: 'utf-8' }).filter(f => f.endsWith('.tpl')) + tplList.forEach(t => { + const tplName = basename(t).replace('.tpl', '') + const tpl = readFileSync(`${tplDir}/${tplName}.tpl`, { encoding: 'utf-8' }) + templates[tplName] = tpl + }) +} + + +const generate = async (localSchema?: boolean) => { + + console.log('>> Local schema: ' + (localSchema || false) + '\n') + + if (!localSchema) { + + let currentVersion = '0.0.0' + + try { + const currentSchema = apiSchema.current() + currentVersion = currentSchema.info.version + } catch (err) { + console.log('No current local schema available') + } + + const schemaInfo = await apiSchema.download() + + if (schemaInfo.version === currentVersion) { + console.log('No new OpenAPI schema version: ' + currentVersion) + return + } + else console.log(`New OpenAPI schema version: ${currentVersion} --> ${schemaInfo.version}`) + + } + + const schemaPath = apiSchema.localPath + if (!existsSync(schemaPath)) { + console.log('Cannot find schema file: ' + schemaPath) + return + } + + console.log('Generating SDK resources from schema ' + schemaPath) + + const schema = apiSchema.parse(schemaPath) + global.version = schema.version + + + // Remove redundant components and force usage of global resource component + fixSchema(schema) + // console.log(inspect(schema, false, null, true)) + + + loadTemplates() + + // Initialize source dir + const resDir = 'src/resources' + if (existsSync(resDir)) rmSync(resDir, { recursive: true }) + mkdirSync(resDir, { recursive: true }) + + // Initialize test dir + const testDir = 'specs/resources' + if (existsSync(testDir)) rmSync(testDir, { recursive: true }) + mkdirSync(testDir, { recursive: true }) + + + // Check singletons + Object.entries(schema.resources).forEach(([type, res]) => { + if (Object.values(res.operations).some(op => op.singleton)) { + global.singletons[type] = Object.keys(res.components)[0] + } + }) + + const resources: { [key: string]: ApiRes } = {} + + Object.entries(schema.resources).forEach(([type, res]) => { + + const name = Inflector.pluralize(Inflector.camelize(type)) as string + + const tplRes = generateResource(type, name, res) + writeFileSync(`${resDir}/${type}.ts`, tplRes) + console.log('Generated resource ' + name) + + const tplSpec = generateSpec(type, name, res) + writeFileSync(`${testDir}/${type}.spec.ts`, tplSpec) + console.log('Generated spec ' + name) + + + const models = Object.keys(res.components) + const singleton = Object.values(res.operations).some(op => op.singleton) + const operations = Object.keys(res.operations).filter(op => ['retrieve', 'list', 'create', 'update', 'delete'].includes(op)) as OperationType[] + const taggable = Object.keys(res.operations).includes('tags') + const versionable = Object.keys(res.operations).includes('versions') + + resources[type] = { + type, + apiClass: name, + models, + singleton, + operations: singleton? [] : operations, + taggable, + versionable + } + + }) + + + updateApiResources(resources) + updateSdkInterfaces(resources) + updateModelTypes(resources) + + console.log(`SDK generation completed [${global.version}].\n`) + +} + + +const findLine = (str: string, lines: string[]): { text: string, index: number, offset: number } => { + let idx = 0 + for (const l of lines) { + const i = l.indexOf(str) + if (i > -1) return { text: l, index: idx, offset: i } + else idx++ + } + return { text: '', index: -1, offset: -1 } +} + + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const tabsCount = (template: string): number => { + return template.match(/##__TAB__##/g)?.length || 0 +} + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const tabsString = (num: number): string => { + let str = '' + for (let i = 0; i < num; i++) str += '\t' + return str +} + + +const updateSdkInterfaces = (resources: { [key: string]: ApiRes }): void => { + + const cl = readFileSync('src/commercelayer.ts', { encoding: 'utf-8' }) + + const lines = cl.split('\n') + + // OpenAPI schema version + if (global.version) { + const schemaLine = findLine('const OPEN_API_SCHEMA_VERSION', lines) + if (schemaLine.index >= 0) lines[schemaLine.index] = `const OPEN_API_SCHEMA_VERSION = '${global.version}'` + } + + // Definitions + const defTplLine = findLine('##__CL_RESOURCES_DEF_TEMPLATE::', lines) + const defTplIdx = defTplLine.offset + '##__CL_RESOURCES_DEF_TEMPLATE::'.length + 1 + const defTpl = defTplLine.text.substring(defTplIdx) + + const definitions: string[] = [] + Object.entries(resources).forEach(([type, res]) => { + let def = defTpl + def = def.replace(/##__TAB__##/g, '\t') + def = def.replace('##__RESOURCE_TYPE__##', type) + def = def.replace('##__RESOURCE_CLASS__##', res.apiClass) + definitions.push(def) + }) + + const defStartIdx = findLine('##__CL_RESOURCES_DEF_START__##', lines).index + 2 + const defStopIdx = findLine('##__CL_RESOURCES_DEF_STOP__##', lines).index + lines.splice(defStartIdx, defStopIdx - defStartIdx, ...definitions) + + + // Initializations + const iniTplLine = findLine('##__CL_RESOURCES_INIT_TEMPLATE::', lines) + const iniTplIdx = iniTplLine.offset + '##__CL_RESOURCES_INIT_TEMPLATE::'.length + 1 + const iniTpl = iniTplLine.text.substring(iniTplIdx) + + const initializations: string[] = [] + Object.entries(resources).forEach(([type, res]) => { + let ini = iniTpl + ini = ini.replace(/##__TAB__##/g, '\t') + ini = ini.replace('##__RESOURCE_TYPE__##', type) + ini = ini.replace('##__RESOURCE_CLASS__##', res.apiClass) + initializations.push(ini) + }) + + const iniStartIdx = findLine('##__CL_RESOURCES_INIT_START__##', lines).index + 2 + const iniStopIdx = findLine('##__CL_RESOURCES_INIT_STOP__##', lines).index + lines.splice(iniStartIdx, iniStopIdx - iniStartIdx, ...initializations) + + + writeFileSync('src/commercelayer.ts', lines.join('\n'), { encoding: 'utf-8' }) + + console.log('API interfaces generated.') + +} + + +const updateModelTypes = (resources: { [key: string]: ApiRes }): void => { + + const cl = readFileSync('src/model.ts', { encoding: 'utf-8' }) + + const lines = cl.split('\n') + + // Exports + const expTplLine = findLine('##__MODEL_TYPES_TEMPLATE::', lines) + const expTplIdx = expTplLine.offset + '##__MODEL_TYPES_TEMPLATE::'.length + 1 + const expTpl = expTplLine.text.substring(expTplIdx) + + const exports: string[] = [copyrightHeader(templates.header)] + const types: string[] = [] + Object.entries(resources).forEach(([type, res]) => { + let exp = expTpl + exp = exp.replace(/##__TAB__##/g, '\t') + exp = exp.replace('##__RESOURCE_TYPE__##', type) + exp = exp.replace('##__RESOURCE_MODELS__##', res.models.join(', ')) + exports.push(exp) + types.push(`\t'${type}'`) + }) + + const expStartIdx = findLine('##__MODEL_TYPES_START__##', lines).index + 2 + const expStopIdx = findLine('##__MODEL_TYPES_STOP__##', lines).index + lines.splice(expStartIdx, expStopIdx - expStartIdx, ...exports) + + + writeFileSync('src/model.ts', lines.join('\n'), { encoding: 'utf-8' }) + + console.log('Model types generated.') + +} + + +const updateApiResources = (resources: { [key: string]: ApiRes }): void => { + + const cl = readFileSync('src/api.ts', { encoding: 'utf-8' }) + + const lines = cl.split('\n') + + // Exports + const expTplLine = findLine('##__API_RESOURCES_TEMPLATE::', lines) + const expTplIdx = expTplLine.offset + '##__API_RESOURCES_TEMPLATE::'.length + 1 + const expTpl = expTplLine.text.substring(expTplIdx) + + + const exports: string[] = [copyrightHeader(templates.header)] + const types: string[] = [] + + const singletons: string[] = [] + const listables: string[] = [] + const creatables: string[] = [] + const updatables: string[] = [] + const deletables: string[] = [] + const taggables: string[] = [] + const versionables: string[] = [] + + Object.entries(resources).forEach(([type, res]) => { + + let exp = expTpl + exp = exp.replace(/##__TAB__##/g, '\t') + exp = exp.replace('##__RESOURCE_TYPE__##', type) + exp = exp.replace('##__RESOURCE_CLASS__##', res.apiClass) + exports.push(exp) + const tabType = `\t'${type}'` + types.push(tabType) + + if (res.singleton) singletons.push(tabType) + if (res.operations.includes('list')) listables.push(tabType) + if (res.operations.includes('create')) creatables.push(tabType) + if (res.operations.includes('update')) updatables.push(tabType) + if (res.operations.includes('delete')) deletables.push(tabType) + if (res.taggable) taggables.push(tabType) + if (res.versionable) versionables.push(tabType) + + }) + + const expStartIdx = findLine('##__API_RESOURCES_START__##', lines).index + 2 + const expStopIdx = findLine('##__API_RESOURCES_STOP__##', lines).index + lines.splice(expStartIdx, expStopIdx - expStartIdx, ...exports) + + const typeStartIdx = findLine('##__API_RESOURCE_TYPES_START__##', lines).index + 1 + const typeStopIdx = findLine('##__API_RESOURCE_TYPES_STOP__##', lines).index + lines.splice(typeStartIdx, typeStopIdx - typeStartIdx, types.join('\n|')) + + const resStartIdx = findLine('##__API_RESOURCE_LIST_START__##', lines).index + 1 + const resStopIdx = findLine('##__API_RESOURCE_LIST_STOP__##', lines).index + lines.splice(resStartIdx, resStopIdx - resStartIdx, types.join(',\n')) + + const rsStartIdx = findLine('##__API_RESOURCE_SINGLETON_START__##', lines).index + 1 + const rsStopIdx = findLine('##__API_RESOURCE_SINGLETON_STOP__##', lines).index + lines.splice(rsStartIdx, rsStopIdx - rsStartIdx, singletons.join(',\n')) + + /* + const mapStartIdx = findLine('##__API_RESOURCE_MAP_START__##', lines).index + 1 + const mapStopIdx = findLine('##__API_RESOURCE_MAP_STOP__##', lines).index + lines.splice(mapStartIdx, mapStopIdx - mapStartIdx, + Object.keys(resources).map(t => `\t${t}: { name: '${Inflector.singularize(t)}', type: '${t}', api: '${t}' }`).join(',\n') + ) + */ + + const rlStartIdx = findLine('##__API_RESOURCE_NOT_LISTABLE_START__##', lines).index + 1 + const rlStopIdx = findLine('##__API_RESOURCE_NOT_LISTABLE_STOP__##', lines).index + lines.splice(rlStartIdx, rlStopIdx - rlStartIdx, singletons.join('\n|')) + + const rcStartIdx = findLine('##__API_RESOURCE_CREATABLE_START__##', lines).index + 1 + const rcStopIdx = findLine('##__API_RESOURCE_CREATABLE_STOP__##', lines).index + lines.splice(rcStartIdx, rcStopIdx - rcStartIdx, creatables.join('\n|')) + + const ruStartIdx = findLine('##__API_RESOURCE_UPDATABLE_START__##', lines).index + 1 + const ruStopIdx = findLine('##__API_RESOURCE_UPDATABLE_STOP__##', lines).index + lines.splice(ruStartIdx, ruStopIdx - ruStartIdx, updatables.join('\n|')) + + const rdStartIdx = findLine('##__API_RESOURCE_DELETABLE_START__##', lines).index + 1 + const rdStopIdx = findLine('##__API_RESOURCE_DELETABLE_STOP__##', lines).index + lines.splice(rdStartIdx, rdStopIdx - rdStartIdx, deletables.join('\n|')) + + const rtStartIdx = findLine('##__API_RESOURCE_TAGGABLE_START__##', lines).index + 1 + const rtStopIdx = findLine('##__API_RESOURCE_TAGGABLE_STOP__##', lines).index + lines.splice(rtStartIdx, rtStopIdx - rtStartIdx, taggables.join('\n|')) + + const rvStartIdx = findLine('##__API_RESOURCE_VERSIONABLE_START__##', lines).index + 1 + const rvStopIdx = findLine('##__API_RESOURCE_VERSIONABLE_STOP__##', lines).index + lines.splice(rvStartIdx, rvStopIdx - rvStartIdx, versionables.join('\n|')) + + + writeFileSync('src/api.ts', lines.join('\n'), { encoding: 'utf-8' }) + + console.log('API resources generated.') + +} + + +const generateSpec = (type: string, name: string, resource: Resource): string => { + + let spec = templates.spec + + // Remove unsupported operations + const lines = spec.split('\n') + + const allOperations = ['list', 'create', 'retrieve', 'update', 'delete', 'singleton'] + + // Generate CRUD operations specs + allOperations.forEach(op => { + if (!Object.values(resource.operations).map(o => { + if ((o.name === 'list') && o.singleton) return 'singleton' + else return o.name + }).includes(op)) { + const opStartIdx = findLine(`spec.${op}.start`, lines).index - 2 + const opStopIdx = findLine(`spec.${op}.stop`, lines).index + 2 + lines.splice(opStartIdx, opStopIdx - opStartIdx, '') + } + }) + + spec = lines.join('\n') + + + if (CONFIG.RELATIONSHIP_FUNCTIONS) { + // Generate relationships operations specs + Object.keys(resource.operations).filter(o => !allOperations.includes(o)).forEach(o => { + const op = resource.operations[o] + if (op.relationship) { + + let specRel = templates.spec_relationship.split('\n').join('\n\t') + + specRel = specRel.replace(/##__OPERATION_NAME__##/g, op.name) + specRel = specRel.replace(/##__RELATIONSHIP_TYPE__##/g, op.relationship.type) + spec = spec.replace(/##__RELATIONSHIP_SPECS__##/g, '\n\n\t' + specRel + '\n\t##__RELATIONSHIP_SPECS__##') + + } + }) + } + + + if (CONFIG.TRIGGER_FUNCTIONS) { + // Generate triggers operations specs + const compUpdKey = Object.keys(resource.components).find(c => c.endsWith('Update')) + if (compUpdKey) { + const compUpd = resource.components[compUpdKey] + const triggers = Object.values(compUpd.attributes).filter(a => a.name.startsWith('_') ) + if (triggers.length > 0) { + const tplt = templates.spec_trigger.split('\n').join('\n\t') + for (const trigger of triggers) { + const triggerValue = (trigger.type === 'boolean')? 'true' : `randomValue('${trigger.type}')` + const triggerParams = (trigger.type === 'boolean')? 'id' : 'id, triggerValue' + let specTrg = tplt + specTrg = specTrg.replace(/##__OPERATION_NAME__##/g, trigger.name) + specTrg = specTrg.replace(/##__TRIGGER_VALUE__##/g, triggerValue) + specTrg = specTrg.replace(/##__TRIGGER_PARAMS__##/g, triggerParams) + spec = spec.replace(/##__TRIGGER_SPECS__##/g, '\n\n\t' + specTrg + '\n\t##__TRIGGER_SPECS__##') + } + } + } + } + + + // Header + spec = copyrightHeader(spec) + + spec = spec.replace(/##__RESOURCE_CLASS__##/g, name) + spec = spec.replace(/##__RESOURCE_TYPE__##/g, type) + // Clear unused placeholders + spec = spec.replace(/##__RELATIONSHIP_SPECS__##/g, '') + spec = spec.replace(/##__TRIGGER_SPECS__##/g, '') + + if (resource.operations.create) { + + let obj = '{\n' + + // Attriburtes + const reqType = resource.operations.create.requestType + const attributes = reqType ? resource.components[reqType].attributes : {} + const required = Object.values(attributes).filter(attr => attr.required) + // required.forEach(r => obj += `\t\t\t${r.name}: ${inspect(randomValue(r.type, r.name))},\n`) + required.forEach(r => obj += `\t\t\t${r.name}: randomValue('${r.type}', '${r.name}'),\n`) + + // Relationships + const relationships = reqType ? resource.components[reqType].relationships : {} + const filtered = Object.values(relationships).filter(rel => !rel.deprecated) + filtered.forEach(f => { + let relVal: string | string[] = `clp.${f.type}.relationship(TestData.id)` + if (f.cardinality === 'to_many') relVal = `[ ${relVal} ]` + obj += `\t\t\t${f.name}: ${relVal},\n` + }) + + obj += '\t\t}\n' + + spec = spec.replace(/##__RESOURCE_ATTRIBUTES_CREATE__##/g, obj) + + } + + const modelName = String(Object.keys(resource.components)[0].replace(/(Create|Update)$/g, '')) + spec = spec.replace(/##__RESOURCE_MODEL__##/g, modelName) + + + return spec + +} + + +const copyrightHeader = (template: string): string => { + + // Header + const now = new Date() + const year = String(now.getFullYear()) + const date = `${String(now.getDate()).padStart(2, '0')}-${String(now.getMonth() + 1).padStart(2, '0')}-${year}` + template = template.replace(/##__CURRENT_YEAR__##/g, year) + template = template.replace(/##__CURRENT_DATE__##/g, date) + if (global.version) template = template.replace(/##__SCHEMA_VERSION__##/g, global.version) + + return template + +} + + +const triggerFunctions = (type: string, name: string, resource: Resource, operations: string[]): void => { + + const resName = name + const compSuffix = 'Update' + + const compUpdKey = Object.keys(resource.components).find(c => c.endsWith(compSuffix)) + if (compUpdKey) { + const compUpd = resource.components[compUpdKey] + const triggers = Object.values(compUpd.attributes).filter(a => a.name.startsWith('_') ) + if (triggers.length > 0) { + const tplt = templates.trigger + for (const trigger of triggers) { + + const resId = `${snakeCase(type)}Id` + const op: Operation = { + type, + path: `/${type}/{${resId}}`, + name: trigger.name, + singleton: false, + requestType: compUpdKey, + responseType: compUpdKey.replace(compSuffix, ''), + id: resId, + trigger: true + } + + const placeholders: Record = {} + if (trigger.type !== 'boolean') placeholders.trigger_value = fixAttributeType({ name: '', type: trigger.type, fetchable: true, required: false, enum: [] }) + + const tpltOp = templatedOperation(resName, trigger.name, op, tplt, placeholders) + operations.push(tpltOp.operation) + + } + } + } + +} + + +const generateResource = (type: string, name: string, resource: Resource): string => { + + let res = templates.resource + const operations: string[] = [] + + const resName = name + + const resModelInterface = Inflector.singularize(resName) + let resModelType = 'ApiResource' + + const declaredTypes: Set = new Set([resModelInterface]) + const declaredTypesDef: string[] = [] + // const declaredEnums: ComponentEnums = {} + const declaredImportsModels: Set = new Set() + const declaredImportsCommon: Set = new Set(['ResourceId']) + + + // Header + res = copyrightHeader(res) + + + // Operations + const qryMod = new Set() + const resMod = new Set() + Object.entries(resource.operations).forEach(([opName, op]) => { + const tpl = op.singleton ? ((opName === 'update')? templates['singleton_update'] : templates['singleton']) : templates[opName] + if (op.singleton) resModelType = 'ApiSingleton' + if (tpl) { + if (['create', 'update'].includes(opName)) qryMod.add('QueryParamsRetrieve') + if (['retrieve', 'list'].includes(opName)) { + /* do nothing: + retrieve operation is common to all resoucres + list operation is common to all non singleton resoucres + */ + } + else { + const tplOp = templatedOperation(resName, opName, op, tpl) + operations.push(tplOp.operation) + tplOp.types.forEach(t => { declaredTypes.add(t) }) + } + } + else { + if (op.relationship && CONFIG.RELATIONSHIP_FUNCTIONS) { + const tplr = templates[`relationship_${op.relationship.cardinality.replace('to_', '')}`] + const tplrOp = templatedOperation(resName, opName, op, tplr) + if (op.relationship.cardinality === Cardinality.to_one) qryMod.add('QueryParamsRetrieve') + else + if (op.relationship.cardinality === Cardinality.to_many) { + qryMod.add('QueryParamsList') + resMod.add('ListResponse') + } + operations.push(tplrOp.operation) + } + else + if (op.action && CONFIG.ACTION_FUNCTIONS) { + const tpla = templates['action'] + const tplaOp = templatedOperation(resName, opName, op, tpla) + operations.push(tplaOp.operation) + tplaOp.typesDef.forEach(t => { declaredTypesDef.push(t) }) + } + else console.log('Unknown operation: ' + opName) + } + }) + + + // Trigger functions (only boolean) + if (CONFIG.TRIGGER_FUNCTIONS) triggerFunctions(type, resName, resource, operations) + + + if (operations && (operations.length > 0)) declaredImportsCommon.add('ResourcesConfig') + + res = res.replace(/##__RESOURCE_MODEL_TYPE__##/g, resModelType) + res = res.replace(/##__RESPONSE_MODELS__##/g, (resMod.size > 0) ? `, ${Array.from(resMod).join(', ')}`: '') + res = res.replace(/##__MODEL_RESOURCE_INTERFACE__##/g, resModelInterface) + res = res.replace(/##__IMPORT_RESOURCE_COMMON__##/, Array.from(declaredImportsCommon).join(', ')) + + const importQueryModels = (qryMod.size > 0)? `import type { ${Array.from(qryMod).sort().reverse().join(', ')} } from '../query'` : '' + res = res.replace(/##__IMPORT_QUERY_MODELS__##/, importQueryModels) + + + // Resource definition + res = res.replace(/##__RESOURCE_TYPE__##/g, type) + res = res.replace(/##__RESOURCE_CLASS__##/g, resName) + + const resourceOperations = (operations && (operations.length > 0))? operations.join('\n\n\t') : '' + res = res.replace(/##__RESOURCE_OPERATIONS__##/, resourceOperations) + + + // Interfaces export + const typesArray = Array.from(declaredTypes) + res = res.replace(/##__EXPORT_RESOURCE_TYPES__##/g, typesArray.join(', ')) + const typesDefArray = Array.from(declaredTypesDef) + res = res.replace(/##__EXPORT_RESOURCE_TYPES_DEF__##/g, (typesDefArray.length > 0)? `${typesDefArray.join('\n')}\n` : '') + + // Interfaces and types definition + const modelInterfaces: string[] = [] + const resourceInterfaces: string[] = [] + const relationshipTypes: Set = new Set() + + typesArray.forEach(t => { + const cudSuffix = getCUDSuffix(t) + resourceInterfaces.push(`Resource${cudSuffix}`) + const tplCmp = templatedComponent(resName, t, resource.components[t]) + tplCmp.models.forEach(m => declaredImportsModels.add(m)) + modelInterfaces.push(tplCmp.component) + if (cudSuffix) tplCmp.models.forEach(t => relationshipTypes.add(t)) + }) + res = res.replace(/##__MODEL_INTERFACES__##/g, modelInterfaces.join('\n\n\n')) + res = res.replace(/##__RESOURCE_INTERFACES__##/g, resourceInterfaces.join(', ')) + + + // Relationships definition + const relTypesArray = Array.from(relationshipTypes).map(i => `type ${i}Rel = ResourceRel & { type: ${i}Type }`) + res = res.replace(/##__RELATIONSHIP_TYPES__##/g, relTypesArray.length ? (relTypesArray.join('\n') + '\n') : '') + + // Resources import + const impResMod: string[] = Array.from(declaredImportsModels) + .filter(i => !typesArray.includes(i)) // exludes resource self reference + .map(i => { + const resFileName = snakeCase(Object.values(global.singletons).includes(i)? i : Inflector.pluralize(i)) + return `import type { ${i}${relationshipTypes.has(i)? `, ${i}Type` : ''} } from './${resFileName}'` + }) + const importStr = impResMod.join('\n') + (impResMod.length ? '\n' : '') + res = res.replace(/##__IMPORT_RESOURCE_MODELS__##/g, importStr) + + // Enum types definitions + + + return res + +} + + +const templatedOperation = (res: string, name: string, op: Operation, tpl: string, placeholders?: Record): { operation: string, types: string[], typesDef: string[] } => { + + let operation = tpl + const types: string[] = [] + const typesDef: string[] = [] + + operation = operation.replace(/##__OPERATION_NAME__##/g, name) + operation = operation.replace(/##__RESOURCE_CLASS__##/g, res) + + if (op.requestType) { + const requestType = op.requestType + operation = operation.replace(/##__RESOURCE_REQUEST_CLASS__##/g, requestType) + if (isObjectType(requestType)) { + const typeDef = `export type ${Inflector.camelize(op.name)}DataType = { ${Object.entries(op.requestTypeDef).map(([k, v]: [string, any]) => `${k}${v.nullable? '?' : ''}: ${v.type}`).join(', ')} }` + typesDef.push(typeDef) + } + else if (!types.includes(requestType)) types.push(requestType) + } + if (op.responseType) { + const responseType = op.responseType + operation = operation.replace(/##__RESOURCE_RESPONSE_CLASS__##/g, responseType) + if (!types.includes(responseType)) types.push(responseType) + } + + const opIdVar = op.id? Inflector.camelize(op.id, true) : '' + if (op.relationship) { // Relationship + operation = operation.replace(/##__RELATIONSHIP_TYPE__##/g, op.relationship.type) + operation = operation.replace(/##__RELATIONSHIP_PATH__##/g, op.path.substring(1).replace('{' + op.id, '${_' + opIdVar)) + operation = operation.replace(/##__RESOURCE_ID__##/g, opIdVar) + operation = operation.replace(/##__MODEL_RESOURCE_INTERFACE__##/g, Inflector.singularize(res)) + } + else + if (op.trigger) { // Trigger + operation = operation.replace(/##__RESOURCE_ID__##/g, opIdVar) + operation = operation.replace(/##__MODEL_RESOURCE_INTERFACE__##/g, Inflector.singularize(res)) + operation = operation.replace(/##__TRIGGER_VALUE__##/, placeholders?.trigger_value? ` triggerValue: ${ placeholders.trigger_value},` : '') + operation = operation.replace(/##__TRIGGER_VALUE_TYPE__##/, placeholders?.trigger_value? 'triggerValue' : 'true') + } + else + if (op.action) { // Action + operation = operation.replace(/##__ACTION_PATH__##/g, op.path.substring(1).replace('{' + op.id, '${_' + opIdVar)) + operation = operation.replace(/##__RESOURCE_ID__##/g, opIdVar) + operation = operation.replace(/##__MODEL_RESOURCE_INTERFACE__##/g, Inflector.singularize(res)) + operation = operation.replace(/##__ACTION_PAYLOAD_PARAM__##/g, isObjectType(op.requestType)? ` payload: ${Inflector.camelize(op.name)}DataType,` : '') + operation = operation.replace(/##__ACTION_PAYLOAD__##/g, isObjectType(op.requestType)? ' ...payload ' : '') + operation = operation.replace(/##__ACTION_COMMAND__##/g, op.type) + } + + if (placeholders) Object.entries(placeholders).forEach(([key, val]) => { + const plh = (key.startsWith('##__') && key.endsWith('__##'))? key : `##__${key.toUpperCase()}__##` + operation = operation.replace(key, val) + }) + + operation = operation.replace(/\n/g, '\n\t') + + + return { operation, types, typesDef } + +} + + +const fixAttributeType = (attr: Attribute): string => { + if (attr.enum?.length > 0) return `${attr.enum.map(a => `'${a}'`).join(' | ')}` + else + switch (attr.type) { + case 'integer': return 'number' + case 'object': return 'Record' + case 'object[]': return 'Array>' + default: return attr.type + } +} + + +const getCUDSuffix = (name: string): string => { + const suffixes = ['Create', 'Update', 'Delete'] + let suffix = '' + if (name) { + suffixes.some(x => { + if (name.endsWith(x)) { + suffix = x + return true + } + return false + }) + } + return suffix +} + +const isCUDModel = (name: string): boolean => { + return (name !== undefined) && (getCUDSuffix(name) !== '') +} + + +type ComponentEnums = { [key: string]: string } + +const templatedComponent = (res: string, name: string, cmp: Component): { component: string, models: string[], enums: ComponentEnums } => { + + const cudModel = isCUDModel(name) + + const models: string[] = [] + const enums: ComponentEnums = {} + + // Attributes + const attributes = Object.values(cmp.attributes) + const fields: string[] = [] + attributes.forEach(a => { + if (!['type', 'id', 'reference', 'reference_origin', 'metadata', 'created_at', 'updated_at'].includes(a.name)) { + if (cudModel || a.fetchable) { + let attrType = fixAttributeType(a) + if (a.enum) enums[a.name] = attrType + fields.push(`${a.name}${a.required ? '' : '?'}: ${attrType}${a.required ? '' : ' | null'}`) + } + } + }) + + // Specific resource type + if (!cudModel) fields.unshift(`readonly type: ${name}Type\n`) + + // Relationships + const relationships = Object.values(cmp.relationships) + const rels: string[] = [] + relationships.forEach(r => { + if (r.deprecated) { + const deprecated = '/**\n\t* @deprecated This field should not be used as it may be removed in the future without notice\n\t*/\n\t' + rels.push(`${deprecated}${r.name}?: object${(r.cardinality === Cardinality.to_many) ? '[]' : ''}`) + } + else { + + let resName = r.type + + if (resName !== 'object') { + + const relStr = cudModel ? 'Rel' : '' + if (r.polymorphic && r.oneOf) { + resName = r.oneOf.map(o => `${o}${relStr}`).join(' | ') + models.push(...r.oneOf) + } + else { + resName = Inflector.camelize(Inflector.singularize(r.type)) + models.push(resName) + resName += relStr + } + } + + if ((r.cardinality === Cardinality.to_many)) { + if (r.polymorphic) resName = `Array<${resName}>` + else resName += '[]' + } + + rels.push(`${r.name}${r.required ? '' : '?'}: ${resName}${r.required ? '' : ' | null'}`) + + } + }) + + + let component = (fields.length || rels.length) ? templates.model : templates.model_empty + + component = component.replace(/##__RESOURCE_MODEL__##/g, name) + component = component.replace(/##__EXTEND_TYPE__##/g, getCUDSuffix(name)) + + const fieldsStr = (fields.length ? '\n\t' : '') + fields.join('\n\t') + (fields.length && rels.length ? '\n' : '') + const relsStr = rels.join('\n\t') + (rels.length ? '\n' : '') + component = component.replace(/##__RESOURCE_MODEL_FIELDS__##/g, fieldsStr) + component = component.replace(/##__RESOURCE_MODEL_RELATIONSHIPS__##/g, relsStr) + + + return { component, models, enums } + +} + + + +generate(process.argv.indexOf('--local') > -1) diff --git a/gen/openapi.json b/gen/openapi.json new file mode 100644 index 0000000..bb5aa29 --- /dev/null +++ b/gen/openapi.json @@ -0,0 +1,5629 @@ +{ + "openapi": "3.0.1", + "info": { + "title": "Commerce Layer Provisioning API", + "version": "1.0.1", + "contact": { + "name": "API Support", + "url": "https://commercelayer.io", + "email": "support@commercelayer.io" + }, + "description": "Headless Commerce for Global Brands." + }, + "servers": [ + { + "url": "https://provisioning.commercelayer.io", + "description": "Commerce Layer Provisioning API" + }, + { + "url": "https://docs.commercelayer.io/provisioning-api", + "description": "API reference" + } + ], + "paths": { + "/api_credentials": { + "post": { + "operationId": "POST/api_credentials", + "summary": "Creates an API credential", + "description": "Creates an API credential", + "tags": [ + "api_credentials" + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/apiCredentialCreate" + } + } + } + }, + "responses": { + "201": { + "description": "The created API credential object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/apiCredentialResponse" + } + } + } + } + } + }, + "get": { + "operationId": "GET/api_credentials", + "summary": "List all API credentials", + "description": "List all API credentials", + "tags": [ + "api_credentials" + ], + "responses": { + "200": { + "description": "A list of API credential objects", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/apiCredentialResponseList" + } + } + } + } + } + } + }, + "/api_credentials/{apiCredentialId}": { + "get": { + "operationId": "GET/api_credentials/apiCredentialId", + "summary": "Retrieve an API credential", + "description": "Retrieve an API credential", + "parameters": [ + { + "name": "apiCredentialId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "tags": [ + "api_credentials" + ], + "responses": { + "200": { + "description": "The API credential object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/apiCredentialResponse" + } + } + } + } + } + }, + "patch": { + "operationId": "PATCH/api_credentials/apiCredentialId", + "summary": "Updates an API credential", + "description": "Updates an API credential", + "tags": [ + "api_credentials" + ], + "parameters": [ + { + "name": "apiCredentialId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/apiCredentialUpdate" + } + } + } + }, + "responses": { + "200": { + "description": "The updated API credential object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/apiCredentialResponse" + } + } + } + } + } + }, + "delete": { + "operationId": "DELETE/api_credentials/apiCredentialId", + "summary": "Delete an API credential", + "description": "Delete an API credential", + "tags": [ + "api_credentials" + ], + "parameters": [ + { + "name": "apiCredentialId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "204": { + "description": "No content" + } + } + } + }, + "/api_credentials/{apiCredentialId}/organization": { + "get": { + "operationId": "GET/apiCredentialId/organization", + "summary": "Related API credential", + "description": "Related API credential", + "tags": [ + "organizations", + "has_one" + ], + "parameters": [ + { + "name": "apiCredentialId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The organization associated to the API credential" + } + } + } + }, + "/api_credentials/{apiCredentialId}/role": { + "get": { + "operationId": "GET/apiCredentialId/role", + "summary": "Related API credential", + "description": "Related API credential", + "tags": [ + "roles", + "has_one" + ], + "parameters": [ + { + "name": "apiCredentialId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The role associated to the API credential" + } + } + } + }, + "/application_memberships": { + "post": { + "operationId": "POST/application_memberships", + "summary": "Creates an application membership", + "description": "Creates an application membership", + "tags": [ + "application_memberships" + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/applicationMembershipCreate" + } + } + } + }, + "responses": { + "201": { + "description": "The created application membership object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/applicationMembershipResponse" + } + } + } + } + } + }, + "get": { + "operationId": "GET/application_memberships", + "summary": "List all application memberships", + "description": "List all application memberships", + "tags": [ + "application_memberships" + ], + "responses": { + "200": { + "description": "A list of application membership objects", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/applicationMembershipResponseList" + } + } + } + } + } + } + }, + "/application_memberships/{applicationMembershipId}": { + "get": { + "operationId": "GET/application_memberships/applicationMembershipId", + "summary": "Retrieve an application membership", + "description": "Retrieve an application membership", + "parameters": [ + { + "name": "applicationMembershipId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "tags": [ + "application_memberships" + ], + "responses": { + "200": { + "description": "The application membership object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/applicationMembershipResponse" + } + } + } + } + } + }, + "patch": { + "operationId": "PATCH/application_memberships/applicationMembershipId", + "summary": "Updates an application membership", + "description": "Updates an application membership", + "tags": [ + "application_memberships" + ], + "parameters": [ + { + "name": "applicationMembershipId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/applicationMembershipUpdate" + } + } + } + }, + "responses": { + "200": { + "description": "The updated application membership object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/applicationMembershipResponse" + } + } + } + } + } + }, + "delete": { + "operationId": "DELETE/application_memberships/applicationMembershipId", + "summary": "Delete an application membership", + "description": "Delete an application membership", + "tags": [ + "application_memberships" + ], + "parameters": [ + { + "name": "applicationMembershipId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "204": { + "description": "No content" + } + } + } + }, + "/application_memberships/{applicationMembershipId}/api_credential": { + "get": { + "operationId": "GET/applicationMembershipId/api_credential", + "summary": "Related application membership", + "description": "Related application membership", + "tags": [ + "api_credentials", + "has_one" + ], + "parameters": [ + { + "name": "applicationMembershipId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The api_credential associated to the application membership" + } + } + } + }, + "/application_memberships/{applicationMembershipId}/membership": { + "get": { + "operationId": "GET/applicationMembershipId/membership", + "summary": "Related application membership", + "description": "Related application membership", + "tags": [ + "memberships", + "has_one" + ], + "parameters": [ + { + "name": "applicationMembershipId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The membership associated to the application membership" + } + } + } + }, + "/application_memberships/{applicationMembershipId}/organization": { + "get": { + "operationId": "GET/applicationMembershipId/organization", + "summary": "Related application membership", + "description": "Related application membership", + "tags": [ + "organizations", + "has_one" + ], + "parameters": [ + { + "name": "applicationMembershipId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The organization associated to the application membership" + } + } + } + }, + "/application_memberships/{applicationMembershipId}/role": { + "get": { + "operationId": "GET/applicationMembershipId/role", + "summary": "Related application membership", + "description": "Related application membership", + "tags": [ + "roles", + "has_one" + ], + "parameters": [ + { + "name": "applicationMembershipId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The role associated to the application membership" + } + } + } + }, + "/memberships": { + "post": { + "operationId": "POST/memberships", + "summary": "Creates an membership", + "description": "Creates an membership", + "tags": [ + "memberships" + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/membershipCreate" + } + } + } + }, + "responses": { + "201": { + "description": "The created membership object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/membershipResponse" + } + } + } + } + } + }, + "get": { + "operationId": "GET/memberships", + "summary": "List all memberships", + "description": "List all memberships", + "tags": [ + "memberships" + ], + "responses": { + "200": { + "description": "A list of membership objects", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/membershipResponseList" + } + } + } + } + } + } + }, + "/memberships/{membershipId}": { + "get": { + "operationId": "GET/memberships/membershipId", + "summary": "Retrieve an membership", + "description": "Retrieve an membership", + "parameters": [ + { + "name": "membershipId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "tags": [ + "memberships" + ], + "responses": { + "200": { + "description": "The membership object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/membershipResponse" + } + } + } + } + } + }, + "patch": { + "operationId": "PATCH/memberships/membershipId", + "summary": "Updates an membership", + "description": "Updates an membership", + "tags": [ + "memberships" + ], + "parameters": [ + { + "name": "membershipId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/membershipUpdate" + } + } + } + }, + "responses": { + "200": { + "description": "The updated membership object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/membershipResponse" + } + } + } + } + } + }, + "delete": { + "operationId": "DELETE/memberships/membershipId", + "summary": "Delete an membership", + "description": "Delete an membership", + "tags": [ + "memberships" + ], + "parameters": [ + { + "name": "membershipId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "204": { + "description": "No content" + } + } + } + }, + "/memberships/{membershipId}/resend": { + "post": { + "operationId": "POST/memberships/membershipId/resend", + "summary": "Resend invitation", + "description": "Resend invitation for the given membership", + "tags": [ + "memberships" + ], + "parameters": [ + { + "name": "membershipId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": {} + } + }, + "responses": { + "202": { + "description": "Confirmation that the invitation has been sent", + "content": {} + } + } + } + }, + "/memberships/{membershipId}/organization": { + "get": { + "operationId": "GET/membershipId/organization", + "summary": "Related membership", + "description": "Related membership", + "tags": [ + "organizations", + "has_one" + ], + "parameters": [ + { + "name": "membershipId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The organization associated to the membership" + } + } + } + }, + "/memberships/{membershipId}/role": { + "get": { + "operationId": "GET/membershipId/role", + "summary": "Related membership", + "description": "Related membership", + "tags": [ + "roles", + "has_one" + ], + "parameters": [ + { + "name": "membershipId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The role associated to the membership" + } + } + } + }, + "/memberships/{membershipId}/application_memberships": { + "get": { + "operationId": "GET/membershipId/application_memberships", + "summary": "Related membership", + "description": "Related membership", + "tags": [ + "application_memberships", + "has_many" + ], + "parameters": [ + { + "name": "membershipId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The application_memberships associated to the membership" + } + } + } + }, + "/memberships/{membershipId}/versions": { + "get": { + "operationId": "GET/membershipId/versions", + "summary": "Related membership", + "description": "Related membership", + "tags": [ + "versions", + "has_many" + ], + "parameters": [ + { + "name": "membershipId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The versions associated to the membership" + } + } + } + }, + "/organizations": { + "post": { + "operationId": "POST/organizations", + "summary": "Creates an organization", + "description": "Creates an organization", + "tags": [ + "organizations" + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/organizationCreate" + } + } + } + }, + "responses": { + "201": { + "description": "The created organization object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/organizationResponse" + } + } + } + } + } + }, + "get": { + "operationId": "GET/organizations", + "summary": "List all organizations", + "description": "List all organizations", + "tags": [ + "organizations" + ], + "responses": { + "200": { + "description": "A list of organization objects", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/organizationResponseList" + } + } + } + } + } + } + }, + "/organizations/{organizationId}": { + "get": { + "operationId": "GET/organizations/organizationId", + "summary": "Retrieve an organization", + "description": "Retrieve an organization", + "parameters": [ + { + "name": "organizationId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "tags": [ + "organizations" + ], + "responses": { + "200": { + "description": "The organization object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/organizationResponse" + } + } + } + } + } + }, + "patch": { + "operationId": "PATCH/organizations/organizationId", + "summary": "Updates an organization", + "description": "Updates an organization", + "tags": [ + "organizations" + ], + "parameters": [ + { + "name": "organizationId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/organizationUpdate" + } + } + } + }, + "responses": { + "200": { + "description": "The updated organization object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/organizationResponse" + } + } + } + } + } + } + }, + "/organizations/{organizationId}/transfer_ownership": { + "patch": { + "operationId": "PATCH/organizations/organizationId/transfer_ownership", + "summary": "Transfer ownership of an organization", + "description": "Transfers the ownership of an organization to a new owner", + "tags": [ + "organizations" + ], + "parameters": [ + { + "name": "organizationId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "id", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organizations" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + }, + "attributes": { + "type": "object", + "properties": { + "new_owner_email": { + "type": "string", + "description": "The user email of the new owner of the organization.", + "example": "test@commercelayer.io", + "nullable": false + } + } + } + } + } + } + } + } + } + }, + "responses": { + "202": { + "description": "The confirmation of the transfer ownership", + "content": {} + } + } + } + }, + "/organizations/{organizationId}/memberships": { + "get": { + "operationId": "GET/organizationId/memberships", + "summary": "Related organization", + "description": "Related organization", + "tags": [ + "memberships", + "has_many" + ], + "parameters": [ + { + "name": "organizationId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The memberships associated to the organization" + } + } + } + }, + "/organizations/{organizationId}/roles": { + "get": { + "operationId": "GET/organizationId/roles", + "summary": "Related organization", + "description": "Related organization", + "tags": [ + "roles", + "has_many" + ], + "parameters": [ + { + "name": "organizationId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The roles associated to the organization" + } + } + } + }, + "/organizations/{organizationId}/permissions": { + "get": { + "operationId": "GET/organizationId/permissions", + "summary": "Related organization", + "description": "Related organization", + "tags": [ + "permissions", + "has_many" + ], + "parameters": [ + { + "name": "organizationId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The permissions associated to the organization" + } + } + } + }, + "/organizations/{organizationId}/api_credentials": { + "get": { + "operationId": "GET/organizationId/api_credentials", + "summary": "Related organization", + "description": "Related organization", + "tags": [ + "api_credentials", + "has_many" + ], + "parameters": [ + { + "name": "organizationId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The api_credentials associated to the organization" + } + } + } + }, + "/permissions": { + "post": { + "operationId": "POST/permissions", + "summary": "Creates an permission", + "description": "Creates an permission", + "tags": [ + "permissions" + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/permissionCreate" + } + } + } + }, + "responses": { + "201": { + "description": "The created permission object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/permissionResponse" + } + } + } + } + } + }, + "get": { + "operationId": "GET/permissions", + "summary": "List all permissions", + "description": "List all permissions", + "tags": [ + "permissions" + ], + "responses": { + "200": { + "description": "A list of permission objects", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/permissionResponseList" + } + } + } + } + } + } + }, + "/permissions/{permissionId}": { + "get": { + "operationId": "GET/permissions/permissionId", + "summary": "Retrieve an permission", + "description": "Retrieve an permission", + "parameters": [ + { + "name": "permissionId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "tags": [ + "permissions" + ], + "responses": { + "200": { + "description": "The permission object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/permissionResponse" + } + } + } + } + } + }, + "patch": { + "operationId": "PATCH/permissions/permissionId", + "summary": "Updates an permission", + "description": "Updates an permission", + "tags": [ + "permissions" + ], + "parameters": [ + { + "name": "permissionId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/permissionUpdate" + } + } + } + }, + "responses": { + "200": { + "description": "The updated permission object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/permissionResponse" + } + } + } + } + } + } + }, + "/permissions/{permissionId}/organization": { + "get": { + "operationId": "GET/permissionId/organization", + "summary": "Related permission", + "description": "Related permission", + "tags": [ + "organizations", + "has_one" + ], + "parameters": [ + { + "name": "permissionId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The organization associated to the permission" + } + } + } + }, + "/permissions/{permissionId}/role": { + "get": { + "operationId": "GET/permissionId/role", + "summary": "Related permission", + "description": "Related permission", + "tags": [ + "roles", + "has_one" + ], + "parameters": [ + { + "name": "permissionId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The role associated to the permission" + } + } + } + }, + "/permissions/{permissionId}/versions": { + "get": { + "operationId": "GET/permissionId/versions", + "summary": "Related permission", + "description": "Related permission", + "tags": [ + "versions", + "has_many" + ], + "parameters": [ + { + "name": "permissionId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The versions associated to the permission" + } + } + } + }, + "/roles": { + "post": { + "operationId": "POST/roles", + "summary": "Creates an role", + "description": "Creates an role", + "tags": [ + "roles" + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/roleCreate" + } + } + } + }, + "responses": { + "201": { + "description": "The created role object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/roleResponse" + } + } + } + } + } + }, + "get": { + "operationId": "GET/roles", + "summary": "List all roles", + "description": "List all roles", + "tags": [ + "roles" + ], + "responses": { + "200": { + "description": "A list of role objects", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/roleResponseList" + } + } + } + } + } + } + }, + "/roles/{roleId}": { + "get": { + "operationId": "GET/roles/roleId", + "summary": "Retrieve an role", + "description": "Retrieve an role", + "parameters": [ + { + "name": "roleId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "tags": [ + "roles" + ], + "responses": { + "200": { + "description": "The role object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/roleResponse" + } + } + } + } + } + }, + "patch": { + "operationId": "PATCH/roles/roleId", + "summary": "Updates an role", + "description": "Updates an role", + "tags": [ + "roles" + ], + "parameters": [ + { + "name": "roleId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/roleUpdate" + } + } + } + }, + "responses": { + "200": { + "description": "The updated role object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/roleResponse" + } + } + } + } + } + } + }, + "/roles/{roleId}/organization": { + "get": { + "operationId": "GET/roleId/organization", + "summary": "Related role", + "description": "Related role", + "tags": [ + "organizations", + "has_one" + ], + "parameters": [ + { + "name": "roleId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The organization associated to the role" + } + } + } + }, + "/roles/{roleId}/permissions": { + "get": { + "operationId": "GET/roleId/permissions", + "summary": "Related role", + "description": "Related role", + "tags": [ + "permissions", + "has_many" + ], + "parameters": [ + { + "name": "roleId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The permissions associated to the role" + } + } + } + }, + "/roles/{roleId}/memberships": { + "get": { + "operationId": "GET/roleId/memberships", + "summary": "Related role", + "description": "Related role", + "tags": [ + "memberships", + "has_many" + ], + "parameters": [ + { + "name": "roleId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The memberships associated to the role" + } + } + } + }, + "/roles/{roleId}/api_credentials": { + "get": { + "operationId": "GET/roleId/api_credentials", + "summary": "Related role", + "description": "Related role", + "tags": [ + "api_credentials", + "has_many" + ], + "parameters": [ + { + "name": "roleId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The api_credentials associated to the role" + } + } + } + }, + "/roles/{roleId}/versions": { + "get": { + "operationId": "GET/roleId/versions", + "summary": "Related role", + "description": "Related role", + "tags": [ + "versions", + "has_many" + ], + "parameters": [ + { + "name": "roleId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "responses": { + "200": { + "description": "The versions associated to the role" + } + } + } + }, + "/user": { + "get": { + "operationId": "GET/user/userId", + "summary": "Retrieve an user", + "description": "Retrieve an user", + "parameters": [], + "tags": [ + "user", + "singleton" + ], + "responses": { + "200": { + "description": "The user object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/userResponse" + } + } + } + } + } + }, + "patch": { + "operationId": "PATCH/user/userId", + "summary": "Updates an user", + "description": "Updates an user", + "tags": [ + "user", + "singleton" + ], + "parameters": [], + "requestBody": { + "required": true, + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/userUpdate" + } + } + } + }, + "responses": { + "200": { + "description": "The updated user object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/userResponse" + } + } + } + } + } + } + }, + "/versions": { + "get": { + "operationId": "GET/versions", + "summary": "List all versions", + "description": "List all versions", + "tags": [ + "versions" + ], + "responses": { + "200": { + "description": "A list of version objects", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/versionResponseList" + } + } + } + } + } + } + }, + "/versions/{versionId}": { + "get": { + "operationId": "GET/versions/versionId", + "summary": "Retrieve an version", + "description": "Retrieve an version", + "parameters": [ + { + "name": "versionId", + "in": "path", + "schema": { + "type": "string" + }, + "required": true, + "description": "The resource's id" + } + ], + "tags": [ + "versions" + ], + "responses": { + "200": { + "description": "The version object", + "content": { + "application/vnd.api+json": { + "schema": { + "$ref": "#/components/schemas/versionResponse" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "apiCredential": { + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "api_credentials" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The API credential internal name.", + "example": "My app", + "nullable": false + }, + "kind": { + "type": "string", + "description": "The API credential kind, can be one of: `webapp`, `sales_channel`, `integration` or the kind of app you want to fork (e.g. `orders`, `imports`, etc.).", + "example": "sales_channel", + "nullable": false + }, + "confidential": { + "type": "boolean", + "description": "Indicates if the API credential it's confidential.", + "example": true, + "nullable": false + }, + "redirect_uri": { + "type": "string", + "description": "The API credential redirect URI.", + "example": "https://bluebrand.com/img/logo.svg", + "nullable": true + }, + "client_id": { + "type": "string", + "description": "The API credential unique ID.", + "example": "xxxx-yyyy-zzzz", + "nullable": false + }, + "client_secret": { + "type": "string", + "description": "The API credential unique secret.", + "example": "xxxx-yyyy-zzzz", + "nullable": false + }, + "scopes": { + "type": "string", + "description": "The API credential scopes.", + "example": "market:all market:9 market:122 market:6 stock_location:6 stock_location:33", + "nullable": false + }, + "expires_in": { + "type": "integer", + "description": "The lifetime of the access token in seconds (min. `7200`, max. `31536000`. Default is `14400` for Sales channels and `7200` for other client types).", + "example": 7200, + "nullable": true + }, + "mode": { + "type": "string", + "description": "Indicates the environment the resource belongs to (one of `test` or `live`).", + "example": "test", + "nullable": true + }, + "custom": { + "type": "boolean", + "description": "Indicates if the API credential is used to create a custom app (e.g. fork a hosted app).", + "example": false, + "nullable": true + }, + "created_at": { + "type": "string", + "description": "Time at which the resource was created.", + "example": "2018-01-01T12:00:00.000Z", + "nullable": false + }, + "updated_at": { + "type": "string", + "description": "Time at which the resource was last updated.", + "example": "2018-01-01T12:00:00.000Z", + "nullable": false + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE", + "nullable": true + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN", + "nullable": true + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + }, + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organizations" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + } + } + } + } + } + } + }, + "apiCredentialCreate": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "api_credentials" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The API credential internal name.", + "example": "My app" + }, + "kind": { + "type": "string", + "description": "The API credential kind, can be one of: `webapp`, `sales_channel`, `integration` or the kind of app you want to fork (e.g. `orders`, `imports`, etc.).", + "example": "sales_channel" + }, + "redirect_uri": { + "type": "string", + "description": "The API credential redirect URI.", + "example": "https://bluebrand.com/img/logo.svg" + }, + "expires_in": { + "type": "integer", + "description": "The lifetime of the access token in seconds (min. `7200`, max. `31536000`. Default is `14400` for Sales channels and `7200` for other client types).", + "example": 7200 + }, + "mode": { + "type": "string", + "description": "Indicates the environment the resource belongs to (one of `test` or `live`).", + "example": "test" + }, + "custom": { + "type": "boolean", + "description": "Indicates if the API credential is used to create a custom app (e.g. fork a hosted app).", + "example": false + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE" + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN" + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + } + } + }, + "required": [ + "name", + "kind" + ] + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organizations" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "role": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + } + }, + "required": [ + "organization" + ] + } + } + } + } + }, + "apiCredentialUpdate": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "id", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "api_credentials" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The API credential internal name.", + "example": "My app", + "nullable": false + }, + "redirect_uri": { + "type": "string", + "description": "The API credential redirect URI.", + "example": "https://bluebrand.com/img/logo.svg", + "nullable": true + }, + "expires_in": { + "type": "integer", + "description": "The lifetime of the access token in seconds (min. `7200`, max. `31536000`. Default is `14400` for Sales channels and `7200` for other client types).", + "example": 7200, + "nullable": true + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE", + "nullable": true + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN", + "nullable": true + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + }, + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "role": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + } + } + } + } + } + } + }, + "apiCredentialResponse": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + }, + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "api_credentials" + ] + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + } + } + }, + "attributes": { + "$ref": "#/components/schemas/apiCredential/properties/data/properties/attributes" + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organization" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + }, + "role": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "role" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + } + } + } + } + } + } + }, + "apiCredentialResponseList": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/apiCredentialResponse/properties/data" + } + } + } + }, + "applicationMembership": { + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "application_memberships" + ] + }, + "attributes": { + "type": "object", + "properties": { + "filters": { + "type": "object", + "description": "Set of key-value pairs that contains restrictions and scopes of the application membership.", + "example": { + "market_id_in": [ + 202, + 203 + ] + }, + "nullable": true + }, + "created_at": { + "type": "string", + "description": "Time at which the resource was created.", + "example": "2018-01-01T12:00:00.000Z", + "nullable": false + }, + "updated_at": { + "type": "string", + "description": "Time at which the resource was last updated.", + "example": "2018-01-01T12:00:00.000Z", + "nullable": false + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE", + "nullable": true + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN", + "nullable": true + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + }, + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "api_credential": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "api_credentials" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "membership": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "memberships" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "organization": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organizations" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + } + } + } + } + } + } + }, + "applicationMembershipCreate": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "application_memberships" + ] + }, + "attributes": { + "type": "object", + "properties": { + "filters": { + "type": "object", + "description": "Set of key-value pairs that contains restrictions and scopes of the application membership.", + "example": { + "market_id_in": [ + 202, + 203 + ] + } + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE" + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN" + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + } + } + } + }, + "relationships": { + "type": "object", + "properties": { + "api_credential": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "api_credentials" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "membership": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "memberships" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "organization": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organizations" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "role": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + } + }, + "required": [ + "api_credential", + "membership", + "organization", + "role" + ] + } + } + } + } + }, + "applicationMembershipUpdate": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "id", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "application_memberships" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + }, + "attributes": { + "type": "object", + "properties": { + "filters": { + "type": "object", + "description": "Set of key-value pairs that contains restrictions and scopes of the application membership.", + "example": { + "market_id_in": [ + 202, + 203 + ] + }, + "nullable": true + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE", + "nullable": true + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN", + "nullable": true + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + }, + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "role": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + } + } + } + } + } + } + }, + "applicationMembershipResponse": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + }, + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "application_memberships" + ] + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + } + } + }, + "attributes": { + "$ref": "#/components/schemas/applicationMembership/properties/data/properties/attributes" + }, + "relationships": { + "type": "object", + "properties": { + "api_credential": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "api_credential" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + }, + "membership": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "membership" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + }, + "organization": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organization" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + }, + "role": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "role" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + } + } + } + } + } + } + }, + "applicationMembershipResponseList": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/applicationMembershipResponse/properties/data" + } + } + } + }, + "membership": { + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "memberships" + ] + }, + "attributes": { + "type": "object", + "properties": { + "user_email": { + "type": "string", + "description": "The user email.", + "example": "commercelayer@commercelayer.io", + "nullable": false + }, + "user_first_name": { + "type": "string", + "description": "The user first name.", + "example": "John", + "nullable": false + }, + "user_last_name": { + "type": "string", + "description": "The user last name.", + "example": "Doe", + "nullable": false + }, + "status": { + "type": "string", + "description": "The memberships status. One of `pending` (default), `active`.", + "example": "pending", + "nullable": false, + "enum": [ + "pending", + "active" + ] + }, + "owner": { + "type": "boolean", + "description": "Indicates if the user it's the owner of the organization.", + "example": true, + "nullable": false + }, + "created_at": { + "type": "string", + "description": "Time at which the resource was created.", + "example": "2018-01-01T12:00:00.000Z", + "nullable": false + }, + "updated_at": { + "type": "string", + "description": "Time at which the resource was last updated.", + "example": "2018-01-01T12:00:00.000Z", + "nullable": false + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE", + "nullable": true + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN", + "nullable": true + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + }, + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organizations" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "application_memberships": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "application_memberships" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "versions": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "versions" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + } + } + } + } + } + } + }, + "membershipCreate": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "memberships" + ] + }, + "attributes": { + "type": "object", + "properties": { + "user_email": { + "type": "string", + "description": "The user email.", + "example": "commercelayer@commercelayer.io" + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE" + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN" + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + } + } + }, + "required": [ + "user_email" + ] + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organizations" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "role": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "application_memberships": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "application_memberships" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + } + }, + "required": [ + "organization", + "role" + ] + } + } + } + } + }, + "membershipUpdate": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "id", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "memberships" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + }, + "attributes": { + "type": "object", + "properties": { + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE", + "nullable": true + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN", + "nullable": true + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + }, + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "role": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "application_memberships": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "application_memberships" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + } + } + } + } + } + } + }, + "membershipResponse": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + }, + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "memberships" + ] + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + } + } + }, + "attributes": { + "$ref": "#/components/schemas/membership/properties/data/properties/attributes" + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organization" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + }, + "role": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "role" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + }, + "application_memberships": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "application_memberships" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + }, + "versions": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "versions" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + } + } + } + } + } + } + }, + "membershipResponseList": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/membershipResponse/properties/data" + } + } + } + }, + "organization": { + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organizations" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The organization's internal name.", + "example": "The Blue Brand", + "nullable": false + }, + "slug": { + "type": "string", + "description": "The organization's slug name.", + "example": "the-blue-brand", + "nullable": false + }, + "domain": { + "type": "string", + "description": "The organization's domain.", + "example": "the-blue-brand.commercelayer.io", + "nullable": false + }, + "support_phone": { + "type": "string", + "description": "The organization's support phone.", + "example": "+01 30800857", + "nullable": true + }, + "support_email": { + "type": "string", + "description": "The organization's support email.", + "example": "support@bluebrand.com", + "nullable": true + }, + "logo_url": { + "type": "string", + "description": "The URL to the organization's logo.", + "example": "https://bluebrand.com/img/logo.svg", + "nullable": true + }, + "favicon_url": { + "type": "string", + "description": "The URL to the organization's favicon.", + "example": "https://bluebrand.com/img/favicon.ico", + "nullable": true + }, + "primary_color": { + "type": "string", + "description": "The organization's primary color. Format is HEX (starts with `#` and it's followed by six letters and/or numbers).", + "example": "#C8984E", + "nullable": true + }, + "contrast_color": { + "type": "string", + "description": "The organization's contrast color. Format is HEX (starts with `#` and it's followed by six letters and/or numbers).", + "example": "#FFFFCC", + "nullable": true + }, + "gtm_id": { + "type": "string", + "description": "The organization's Google Tag Manager ID.", + "example": "GTM-5FJXX6", + "nullable": true + }, + "gtm_id_test": { + "type": "string", + "description": "The organization's Google Tag Manager ID for test.", + "example": "GTM-5FJXX7", + "nullable": true + }, + "discount_disabled": { + "type": "boolean", + "description": "Indicates if organization has discount disabled.", + "example": false, + "nullable": true + }, + "account_disabled": { + "type": "boolean", + "description": "Indicates if organization has account disabled.", + "example": false, + "nullable": true + }, + "acceptance_disabled": { + "type": "boolean", + "description": "Indicates if organization has acceptance disabled.", + "example": false, + "nullable": true + }, + "max_concurrent_promotions": { + "type": "integer", + "description": "The maximum number of active concurrent promotions allowed for your organization.", + "example": 10, + "nullable": false + }, + "max_concurrent_imports": { + "type": "integer", + "description": "The maximum number of concurrent imports allowed for your organization.", + "example": 30, + "nullable": false + }, + "region": { + "type": "string", + "description": "The region where the organization it's located, default value it's `eu-west-1`.", + "example": "eu-west-1", + "nullable": true + }, + "can_switch_live": { + "type": "boolean", + "description": "Indicates if the organization can switch to live mode.", + "example": false, + "nullable": false + }, + "subscription_totals": { + "type": "object", + "description": "The number of current organizations, markets, memberships, and SKUs associated with the active subscription.", + "example": { + "organizations": 1, + "markets": 0, + "memberships": 0, + "skus": 0 + }, + "nullable": false + }, + "created_at": { + "type": "string", + "description": "Time at which the resource was created.", + "example": "2018-01-01T12:00:00.000Z", + "nullable": false + }, + "updated_at": { + "type": "string", + "description": "Time at which the resource was last updated.", + "example": "2018-01-01T12:00:00.000Z", + "nullable": false + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE", + "nullable": true + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN", + "nullable": true + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + }, + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "memberships": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "memberships" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "roles": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "permissions" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "api_credentials": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "api_credentials" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + } + } + } + } + } + } + }, + "organizationCreate": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organizations" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The organization's internal name.", + "example": "The Blue Brand" + }, + "support_phone": { + "type": "string", + "description": "The organization's support phone.", + "example": "+01 30800857" + }, + "support_email": { + "type": "string", + "description": "The organization's support email.", + "example": "support@bluebrand.com" + }, + "logo_url": { + "type": "string", + "description": "The URL to the organization's logo.", + "example": "https://bluebrand.com/img/logo.svg" + }, + "favicon_url": { + "type": "string", + "description": "The URL to the organization's favicon.", + "example": "https://bluebrand.com/img/favicon.ico" + }, + "primary_color": { + "type": "string", + "description": "The organization's primary color. Format is HEX (starts with `#` and it's followed by six letters and/or numbers).", + "example": "#C8984E" + }, + "contrast_color": { + "type": "string", + "description": "The organization's contrast color. Format is HEX (starts with `#` and it's followed by six letters and/or numbers).", + "example": "#FFFFCC" + }, + "gtm_id": { + "type": "string", + "description": "The organization's Google Tag Manager ID.", + "example": "GTM-5FJXX6" + }, + "gtm_id_test": { + "type": "string", + "description": "The organization's Google Tag Manager ID for test.", + "example": "GTM-5FJXX7" + }, + "discount_disabled": { + "type": "boolean", + "description": "Indicates if organization has discount disabled.", + "example": false + }, + "account_disabled": { + "type": "boolean", + "description": "Indicates if organization has account disabled.", + "example": false + }, + "acceptance_disabled": { + "type": "boolean", + "description": "Indicates if organization has acceptance disabled.", + "example": false + }, + "region": { + "type": "string", + "description": "The region where the organization it's located, default value it's `eu-west-1`.", + "example": "eu-west-1" + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE" + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN" + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + } + } + }, + "required": [ + "name" + ] + }, + "relationships": { + "type": "object", + "properties": {} + } + } + } + } + }, + "organizationUpdate": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "id", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organizations" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The organization's internal name.", + "example": "The Blue Brand", + "nullable": false + }, + "support_phone": { + "type": "string", + "description": "The organization's support phone.", + "example": "+01 30800857", + "nullable": true + }, + "support_email": { + "type": "string", + "description": "The organization's support email.", + "example": "support@bluebrand.com", + "nullable": true + }, + "logo_url": { + "type": "string", + "description": "The URL to the organization's logo.", + "example": "https://bluebrand.com/img/logo.svg", + "nullable": true + }, + "favicon_url": { + "type": "string", + "description": "The URL to the organization's favicon.", + "example": "https://bluebrand.com/img/favicon.ico", + "nullable": true + }, + "primary_color": { + "type": "string", + "description": "The organization's primary color. Format is HEX (starts with `#` and it's followed by six letters and/or numbers).", + "example": "#C8984E", + "nullable": true + }, + "contrast_color": { + "type": "string", + "description": "The organization's contrast color. Format is HEX (starts with `#` and it's followed by six letters and/or numbers).", + "example": "#FFFFCC", + "nullable": true + }, + "gtm_id": { + "type": "string", + "description": "The organization's Google Tag Manager ID.", + "example": "GTM-5FJXX6", + "nullable": true + }, + "gtm_id_test": { + "type": "string", + "description": "The organization's Google Tag Manager ID for test.", + "example": "GTM-5FJXX7", + "nullable": true + }, + "discount_disabled": { + "type": "boolean", + "description": "Indicates if organization has discount disabled.", + "example": false, + "nullable": false + }, + "account_disabled": { + "type": "boolean", + "description": "Indicates if organization has account disabled.", + "example": false, + "nullable": false + }, + "acceptance_disabled": { + "type": "boolean", + "description": "Indicates if organization has acceptance disabled.", + "example": false, + "nullable": false + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE", + "nullable": true + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN", + "nullable": true + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + }, + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": {} + } + } + } + } + }, + "organizationResponse": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + }, + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organizations" + ] + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + } + } + }, + "attributes": { + "$ref": "#/components/schemas/organization/properties/data/properties/attributes" + }, + "relationships": { + "type": "object", + "properties": { + "memberships": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "memberships" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + }, + "roles": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "permissions" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + }, + "api_credentials": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "api_credentials" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + } + } + } + } + } + } + }, + "organizationResponseList": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/organizationResponse/properties/data" + } + } + } + }, + "permission": { + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "permissions" + ] + }, + "attributes": { + "type": "object", + "properties": { + "can_create": { + "type": "boolean", + "description": "Determines if the permission have access to create rights.", + "example": false, + "nullable": false + }, + "can_read": { + "type": "boolean", + "description": "Determines if the permission have access to read rights.", + "example": false, + "nullable": false + }, + "can_update": { + "type": "boolean", + "description": "Determines if the permission have access to update rights.", + "example": false, + "nullable": false + }, + "can_destroy": { + "type": "boolean", + "description": "Determines if the permission have access to destroy rights.", + "example": false, + "nullable": false + }, + "subject": { + "type": "string", + "description": "The resource where this permission is applied.", + "example": "", + "nullable": false + }, + "restrictions": { + "type": "object", + "description": "An object that contains additional restrictions.", + "example": { + "foo": "bar" + }, + "nullable": false + }, + "created_at": { + "type": "string", + "description": "Time at which the resource was created.", + "example": "2018-01-01T12:00:00.000Z", + "nullable": false + }, + "updated_at": { + "type": "string", + "description": "Time at which the resource was last updated.", + "example": "2018-01-01T12:00:00.000Z", + "nullable": false + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE", + "nullable": true + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN", + "nullable": true + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + }, + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organizations" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "versions": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "versions" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + } + } + } + } + } + } + }, + "permissionCreate": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "permissions" + ] + }, + "attributes": { + "type": "object", + "properties": { + "can_create": { + "type": "boolean", + "description": "Determines if the permission have access to create rights.", + "example": false + }, + "can_read": { + "type": "boolean", + "description": "Determines if the permission have access to read rights.", + "example": false + }, + "can_update": { + "type": "boolean", + "description": "Determines if the permission have access to update rights.", + "example": false + }, + "can_destroy": { + "type": "boolean", + "description": "Determines if the permission have access to destroy rights.", + "example": false + }, + "subject": { + "type": "string", + "description": "The resource where this permission is applied.", + "example": "" + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE" + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN" + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + } + } + }, + "required": [ + "can_create", + "can_read", + "can_update", + "can_destroy", + "subject" + ] + }, + "relationships": { + "type": "object", + "properties": { + "role": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + } + }, + "required": [ + "role" + ] + } + } + } + } + }, + "permissionUpdate": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "id", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "permissions" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + }, + "attributes": { + "type": "object", + "properties": { + "can_create": { + "type": "boolean", + "description": "Determines if the permission have access to create rights.", + "example": false, + "nullable": false + }, + "can_read": { + "type": "boolean", + "description": "Determines if the permission have access to read rights.", + "example": false, + "nullable": false + }, + "can_update": { + "type": "boolean", + "description": "Determines if the permission have access to update rights.", + "example": false, + "nullable": false + }, + "can_destroy": { + "type": "boolean", + "description": "Determines if the permission have access to destroy rights.", + "example": false, + "nullable": false + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE", + "nullable": true + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN", + "nullable": true + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + }, + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": {} + } + } + } + } + }, + "permissionResponse": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + }, + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "permissions" + ] + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + } + } + }, + "attributes": { + "$ref": "#/components/schemas/permission/properties/data/properties/attributes" + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organization" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + }, + "role": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "role" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + }, + "versions": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "versions" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + } + } + } + } + } + } + }, + "permissionResponseList": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/permissionResponse/properties/data" + } + } + } + }, + "role": { + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The role name.", + "example": "Custom role", + "nullable": false + }, + "kind": { + "type": "string", + "description": "The kind of role, one of: `custom`, `admin`, `read_only`", + "example": "custom", + "nullable": false + }, + "created_at": { + "type": "string", + "description": "Time at which the resource was created.", + "example": "2018-01-01T12:00:00.000Z", + "nullable": false + }, + "updated_at": { + "type": "string", + "description": "Time at which the resource was last updated.", + "example": "2018-01-01T12:00:00.000Z", + "nullable": false + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE", + "nullable": true + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN", + "nullable": true + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + }, + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organizations" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "permissions" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "memberships": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "memberships" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "api_credentials": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "api_credentials" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + }, + "versions": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "versions" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + } + } + } + } + } + } + }, + "roleCreate": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The role name.", + "example": "Custom role" + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE" + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN" + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + } + } + }, + "required": [ + "name" + ] + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organizations" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + } + } + } + } + } + }, + "required": [ + "organization" + ] + } + } + } + } + }, + "roleUpdate": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "id", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + }, + "attributes": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "The role name.", + "example": "Custom role", + "nullable": false + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE", + "nullable": true + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN", + "nullable": true + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + }, + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": {} + } + } + } + } + }, + "roleResponse": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + }, + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "roles" + ] + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + } + } + }, + "attributes": { + "$ref": "#/components/schemas/role/properties/data/properties/attributes" + }, + "relationships": { + "type": "object", + "properties": { + "organization": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "organization" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + }, + "permissions": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "permissions" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + }, + "memberships": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "memberships" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + }, + "api_credentials": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "api_credentials" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + }, + "versions": { + "type": "object", + "properties": { + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + }, + "related": { + "type": "string", + "description": "URL" + } + } + }, + "data": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "versions" + ] + }, + "id": { + "type": "string", + "description": "The resource ID" + } + } + } + } + } + } + } + } + } + } + }, + "roleResponseList": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/roleResponse/properties/data" + } + } + } + }, + "user": { + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "user" + ] + }, + "attributes": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "The user email.", + "example": "user@commercelayer.io", + "nullable": false + }, + "first_name": { + "type": "string", + "description": "The user first name.", + "example": "John", + "nullable": false + }, + "last_name": { + "type": "string", + "description": "The user last name.", + "example": "Doe", + "nullable": false + }, + "time_zone": { + "type": "string", + "description": "The user preferred timezone.", + "example": "UTC", + "nullable": true + }, + "created_at": { + "type": "string", + "description": "Time at which the resource was created.", + "example": "2018-01-01T12:00:00.000Z", + "nullable": false + }, + "updated_at": { + "type": "string", + "description": "Time at which the resource was last updated.", + "example": "2018-01-01T12:00:00.000Z", + "nullable": false + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE", + "nullable": true + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN", + "nullable": true + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + }, + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": {} + } + } + } + } + }, + "userUpdate": { + "required": [ + "data" + ], + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "id", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "user" + ] + }, + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + }, + "attributes": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "The user email.", + "example": "user@commercelayer.io", + "nullable": false + }, + "first_name": { + "type": "string", + "description": "The user first name.", + "example": "John", + "nullable": false + }, + "last_name": { + "type": "string", + "description": "The user last name.", + "example": "Doe", + "nullable": false + }, + "time_zone": { + "type": "string", + "description": "The user preferred timezone.", + "example": "UTC", + "nullable": true + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE", + "nullable": true + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN", + "nullable": true + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + }, + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": {} + } + } + } + } + }, + "userResponse": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + }, + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "user" + ] + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + } + } + }, + "attributes": { + "$ref": "#/components/schemas/user/properties/data/properties/attributes" + }, + "relationships": { + "type": "object", + "properties": {} + } + } + } + } + }, + "userResponseList": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/userResponse/properties/data" + } + } + } + }, + "version": { + "type": "object", + "properties": { + "data": { + "type": "object", + "required": [ + "type", + "attributes" + ], + "properties": { + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "versions" + ] + }, + "attributes": { + "type": "object", + "properties": { + "resource_type": { + "type": "string", + "description": "The type of the versioned resource.", + "example": "roles", + "nullable": false + }, + "resource_id": { + "type": "string", + "description": "The versioned resource ID.", + "example": "PzdJhdLdYV", + "nullable": false + }, + "event": { + "type": "string", + "description": "The event which generates the version.", + "example": "update", + "nullable": false + }, + "changes": { + "type": "object", + "description": "The object changes payload.", + "example": { + "name": [ + "previous", + "new" + ] + }, + "nullable": false + }, + "who": { + "type": "object", + "description": "Information about who triggered the change, only showed when it's from a JWT token.", + "example": { + "application": { + "id": "DNOPYiZYpn", + "kind": "integration", + "public": true + } + }, + "nullable": false + }, + "created_at": { + "type": "string", + "description": "Time at which the resource was created.", + "example": "2018-01-01T12:00:00.000Z", + "nullable": false + }, + "updated_at": { + "type": "string", + "description": "Time at which the resource was last updated.", + "example": "2018-01-01T12:00:00.000Z", + "nullable": false + }, + "reference": { + "type": "string", + "description": "A string that you can use to add any external identifier to the resource. This can be useful for integrating the resource to an external system, like an ERP, a marketing tool, a CRM, or whatever.", + "example": "ANY-EXTERNAL-REFEFERNCE", + "nullable": true + }, + "reference_origin": { + "type": "string", + "description": "Any identifier of the third party system that defines the reference code.", + "example": "ANY-EXTERNAL-REFEFERNCE-ORIGIN", + "nullable": true + }, + "metadata": { + "type": "object", + "description": "Set of key-value pairs that you can attach to the resource. This can be useful for storing additional information about the resource in a structured format.", + "example": { + "foo": "bar" + }, + "nullable": true + } + } + }, + "relationships": { + "type": "object", + "properties": {} + } + } + } + } + }, + "versionResponse": { + "type": "object", + "properties": { + "data": { + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "The resource's id", + "example": "XGZwpOSrWL" + }, + "type": { + "type": "string", + "description": "The resource's type", + "enum": [ + "versions" + ] + }, + "links": { + "type": "object", + "properties": { + "self": { + "type": "string", + "description": "URL" + } + } + }, + "attributes": { + "$ref": "#/components/schemas/version/properties/data/properties/attributes" + }, + "relationships": { + "type": "object", + "properties": {} + } + } + } + } + }, + "versionResponseList": { + "type": "object", + "properties": { + "data": { + "type": "array", + "items": { + "$ref": "#/components/schemas/versionResponse/properties/data" + } + } + } + } + }, + "securitySchemes": { + "bearerAuth": { + "type": "http", + "scheme": "bearer", + "bearerFormat": "JWT" + } + } + }, + "tags": [ + { + "name": "singleton", + "description": "singleton resource" + }, + { + "name": "api_credentials", + "description": "resource type" + }, + { + "name": "has_one", + "description": "relationship kind" + }, + { + "name": "application_memberships", + "description": "resource type" + }, + { + "name": "memberships", + "description": "resource type" + }, + { + "name": "has_many", + "description": "relationship kind" + }, + { + "name": "organizations", + "description": "resource type" + }, + { + "name": "permissions", + "description": "resource type" + }, + { + "name": "roles", + "description": "resource type" + }, + { + "name": "user", + "description": "resource type" + }, + { + "name": "versions", + "description": "resource type" + } + ], + "security": [ + { + "bearerAuth": [] + } + ] +} \ No newline at end of file diff --git a/gen/schema.ts b/gen/schema.ts new file mode 100644 index 0000000..4129f3f --- /dev/null +++ b/gen/schema.ts @@ -0,0 +1,405 @@ +import { readFileSync, writeFileSync } from 'fs' +import { snakeCase } from 'lodash' +import axios from 'axios' +import { resolve } from 'path' +import { sortObjectFields } from '../src/util' + + +const Inflector = require('inflector-js') + + +const SCHEMA_LOCAL_PATH = resolve('./gen/openapi.json') +const SCHEMA_NAME = 'openapi.json' +const SCHEMA_REMOTE_URL = 'https://data.commercelayer.app/schemas/provisioning/' + SCHEMA_NAME + + +type SchemaInfo = { + remoteUrl?: string; + localPath?: string; + version?: string; +} + + +const downloadSchema = async (url?: string): Promise => { + + const schemaUrl = url || SCHEMA_REMOTE_URL + const schemaOutPath = SCHEMA_LOCAL_PATH + + console.log(`Downloading OpenAPI schema ... [${schemaUrl}]`) + + const response = await axios.get(schemaUrl) + const schema = await response.data + + if (schema) writeFileSync(schemaOutPath, JSON.stringify(schema, null, 4)) + else console.log('OpenAPI schema is empty!') + + const version = schema.info.version + + console.log('OpenAPI schema downloaded: ' + version) + + return { + remoteUrl: schemaUrl, + localPath: schemaOutPath, + version, + } + +} + + +const currentSchema = (): any => { + + const currentSchema = readFileSync(SCHEMA_LOCAL_PATH, { encoding: 'utf-8' }) + const schema = JSON.parse(currentSchema) + + return schema + +} + + +const parseSchema = (path: string): ApiSchema => { + + console.log('Parsing OpenAPI schema ...') + + const apiSchema: any = {} + + const schemaFile = path + const openApi = readFileSync(schemaFile, { encoding: 'utf-8' }) as any + + const schema = JSON.parse(openApi) + + apiSchema.version = schema.info?.version + console.log(`Schema version: ${apiSchema.version}`) + + apiSchema.paths = parsePaths(schema.paths) + apiSchema.components = parseComponents(schema.components.schemas) + + const resources: ResourceMap = {} + const components: ComponentMap = {} + + const specialComponentMatcher = /(Create|Update|ResponseList|ResponseCreated|ResponseUpdated|Response)$/ + + Object.keys(apiSchema.paths).forEach(p => { + const singRes = Inflector.singularize(p) // singularized resource name in snake case format + resources[p] = { + operations: apiSchema.paths[p], + components: {} + } + Object.keys(apiSchema.components).forEach(c => { + if (!specialComponentMatcher.test(c)) components[c] = apiSchema.components[c] + else + if (snakeCase(c.replace(specialComponentMatcher, '')) === singRes) resources[p].components[c] = apiSchema.components[c] + }) + // Sort components + resources[p].components = sortObjectFields(resources[p].components) + }) + + console.log('OpenAPI schema correctly parsed.') + + + return { version: apiSchema.version, resources, components } + +} + + +const operationName = (op: string, id?: string, relOrCmd?: string): string => { + switch (op) { + case 'get': return id ? (relOrCmd || 'retrieve') : 'list' + case 'patch': return id ? (relOrCmd || 'update') : 'update' + case 'delete': return 'delete' + case 'post': return id ? (relOrCmd || 'create') : 'create' + default: return op + } +} + + +const referenceResource = (ref: { '$ref': string }): string | undefined => { + const r = getReference(ref) as string + return r ? Inflector.camelize(r.substring(r.lastIndexOf('/') + 1)) : undefined +} + +const contentSchema = (content: any): any => { + return content["application/vnd.api+json"]?.schema +} + +const referenceContent = (content: any): string | undefined => { + // No content or no response codes + if (!content || !Object.keys(content).length) return undefined + const schema = contentSchema(content) + return schema ? referenceResource(schema) : undefined +} + + +const contentType = (content?: any): string | undefined => { + if (!content) return undefined + const schema = contentSchema(content) + if (!schema) return undefined + return isReference(schema) ? referenceContent(content) : 'object' +} + + +export const isObjectType = (type?: string): boolean => { + return (type !== undefined) && ['object', 'any'].includes(type) +} + + +const parsePaths = (schemaPaths: any[]): PathMap => { + + const paths: PathMap = {} + + for (const p of Object.entries(schemaPaths)) { + + const [pKey, pValue] = p + const relIdx = pKey.indexOf('}/') + 2 + const relOrCmd = (relIdx > 1) ? pKey.substring(relIdx) : undefined + + const id = pKey.substring(pKey.indexOf('{') + 1, pKey.indexOf('}')) + const path = pKey.replace(/\/{.*}/g, '').substring(1) + const slIdx = path.lastIndexOf('/') + const res = (slIdx === -1) ? path : path.substring(0, slIdx) + + const operations: OperationMap = paths[res] || {} + + Object.entries(pValue as object).forEach(o => { + + let skip = false + + const [oKey, oValue] = o + + const op: Operation = { + path: pKey, + type: oKey, + name: operationName(oKey, id, relOrCmd), + singleton: oValue.tags.includes('singleton'), + } + + if (id) op.id = id + if (oValue.requestBody) { + op.requestType = contentType(oValue.requestBody.content) + if (isObjectType(op.requestType)) op.requestTypeDef = contentSchema(oValue.requestBody.content).properties.data.properties.attributes.properties + } + if (oValue.responses) { + const responses = Object.values(oValue.responses) as any[] + if (responses.length > 0) op.responseType = contentType(responses[0].content) + } + + + if (relOrCmd) { + + const tags = oValue.tags as string[] + const relCard = tags.find(t => t.startsWith('has_')) as string + if (!relCard) console.log(`Relationship without cardinality: ${op.name} [${op.path}]`) + const relType = tags.find(t => !t.startsWith('has_')) as string + if (!relType) console.log(`Relationship without type: ${op.name} [${op.path}]`) + + if (relType) { + if (relCard) { + op.relationship = { + name: relOrCmd || '', + type: relType, + polymorphic: false, + cardinality: (relCard === 'has_many') ? Cardinality.to_many : Cardinality.to_one, + required: false, + deprecated: false, + } + op.responseType = Inflector.camelize(Inflector.singularize(op.relationship.type)) + } else { + op.function = operationName(oKey, id), + op.action = true + } + } else skip = true + + } + + if (skip) console.log(`Operation skipped: ${op.name} [${op.path}]`) + else operations[op.name] = op + + }) + + paths[res] = operations + + } + + + return paths + +} + + +const isReference = (obj: any): boolean => { + return (obj.$ref !== undefined) +} + + +const getReference = (obj: any): string | undefined => { + if (obj) return obj['$ref'] + return undefined +} + + +const resolveReference = (schemaComponents: any[], ref: string): any => { + + const segs = ref.replace('#/components/schemas/', '').split('/') + const key = Inflector.camelize(segs.shift() as string, true) + + let reference: any = schemaComponents[key] + segs.forEach(s => reference = reference[s]) + + return reference + +} + + +const parseComponents = (schemaComponents: any[]): ComponentMap => { + + const components: ComponentMap = {} + + for (const c of Object.entries(schemaComponents)) { + + const [cKey, cValue] = c + + // Check component reference + let cmp = (cValue.properties.data.type === 'array') ? cValue.properties.data.items : cValue.properties.data + const cmpRef = getReference(cmp) + if (cmpRef) cmp = resolveReference(schemaComponents, cmpRef) + + // Component type + // const cmpType = cmp.properties.type.enum[0] + + // Check attributes reference + const attributesRef = getReference(cmp.properties.attributes) + const cmpAttributes = attributesRef ? resolveReference(schemaComponents, attributesRef) : cmp.properties.attributes + const cmpRelationships = cmp.properties.relationships + + const attributes: { [key: string]: Attribute } = {} + const requiredAttributes: string[] = cmpAttributes.required || [] + const relationships: { [key: string]: Relationship } = {} + const requiredRelationships: string[] = cmpRelationships.required || [] + + // Attributes + Object.entries(cmpAttributes.properties as object).forEach(a => { + const [aKey, aValue] = a + const fetchable = (aValue.nullable !== undefined) + attributes[aKey] = { + name: aKey, + type: (aValue.type === 'array') ? `${aValue.items.type}[]` : aValue.type, + required: requiredAttributes.includes(aKey) || (fetchable && !aValue.nullable && !cKey.match(/(Create|Update)$/)), + fetchable, + enum: aValue.enum + } + }) + + // Relationships + if (cmpRelationships) { + Object.entries(cmpRelationships.properties as object).forEach(r => { + const [rKey, rValue] = r + const dataObj = rValue.properties.data ? rValue.properties.data : rValue + const typeObj = dataObj.items ? dataObj.items.properties : dataObj.properties + const type = typeObj.type.enum[0] // typeObj.type.default || typeObj.type.example + let oneOf = rValue.oneOf + if (oneOf) oneOf = oneOf.map(referenceResource) + relationships[rKey] = { + name: rKey, + type, + required: requiredRelationships.includes(rKey), + cardinality: (Inflector.pluralize(rKey) === rKey) ? Cardinality.to_many : Cardinality.to_one, + deprecated: rValue.deprecated, + oneOf, + polymorphic: (oneOf !== undefined) && oneOf.length + } + }) + } + + components[Inflector.camelize(cKey)] = { + // type: cmpType, + attributes, + relationships + } + + } + + + return components + +} + + +type ApiSchema = { + version: string, + resources: ResourceMap, + components: ComponentMap +} + + +type Resource = { + components: ComponentMap + operations: OperationMap +} + +type ResourceMap = { + [resource: string]: Resource +} + +type Component = { + // type: string + attributes: { [key: string]: Attribute } + relationships: { [key: string]: Relationship } +} + +type ComponentMap = { + [key: string]: Component +} + +type Attribute = { + type: string + name: string + required: boolean + fetchable: boolean + enum: string[] +} + +enum Cardinality { + to_one = 'to_one', + to_many = 'to_many' +} + +type Relationship = { + type: string + name: string + required: boolean + cardinality: Cardinality + deprecated: boolean + oneOf?: Array + polymorphic: boolean +} + +type PathMap = { [key: string]: OperationMap } + +type OperationMap = { [key: string]: Operation } + +type Operation = { + path: string + type: string + id?: string + name: string + function?: string + requestType?: string + requestTypeDef?: any + responseType?: string + responseTypeDef?: any + singleton: boolean + relationship?: Relationship + trigger?: boolean, + action?: boolean +} + + + +export default { + download: downloadSchema, + parse: parseSchema, + current: currentSchema, + localPath: SCHEMA_LOCAL_PATH, + remoteUrl: SCHEMA_REMOTE_URL, +} + +export { Resource, Operation, Component, ComponentMap, Cardinality, Relationship, ApiSchema, Attribute } \ No newline at end of file diff --git a/gen/templates/action.tpl b/gen/templates/action.tpl new file mode 100644 index 0000000..fe1281d --- /dev/null +++ b/gen/templates/action.tpl @@ -0,0 +1,4 @@ +async ##__OPERATION_NAME__##(##__RESOURCE_ID__##: string | ##__MODEL_RESOURCE_INTERFACE__##,##__ACTION_PAYLOAD_PARAM__## options?: ResourcesConfig): Promise { + const _##__RESOURCE_ID__## = (##__RESOURCE_ID__## as ##__MODEL_RESOURCE_INTERFACE__##).id || ##__RESOURCE_ID__## as string + await this.resources.action('##__ACTION_COMMAND__##', `##__ACTION_PATH__##`, {##__ACTION_PAYLOAD__##}, options) +} \ No newline at end of file diff --git a/gen/templates/create.tpl b/gen/templates/create.tpl new file mode 100644 index 0000000..f6865b6 --- /dev/null +++ b/gen/templates/create.tpl @@ -0,0 +1,3 @@ +async create(resource: ##__RESOURCE_REQUEST_CLASS__##, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise<##__RESOURCE_RESPONSE_CLASS__##> { + return this.resources.create<##__RESOURCE_REQUEST_CLASS__##, ##__RESOURCE_RESPONSE_CLASS__##>({ ...resource, type: ##__RESOURCE_CLASS__##.TYPE }, params, options) +} \ No newline at end of file diff --git a/gen/templates/delete.tpl b/gen/templates/delete.tpl new file mode 100644 index 0000000..0f65508 --- /dev/null +++ b/gen/templates/delete.tpl @@ -0,0 +1,3 @@ +async delete(id: string | ResourceId, options?: ResourcesConfig): Promise { + await this.resources.delete((typeof id === 'string')? { id, type: ##__RESOURCE_CLASS__##.TYPE } : id, options) +} \ No newline at end of file diff --git a/gen/templates/header.tpl b/gen/templates/header.tpl new file mode 100644 index 0000000..beed24b --- /dev/null +++ b/gen/templates/header.tpl @@ -0,0 +1,3 @@ +/** + * ©##__CURRENT_YEAR__## Commerce Layer Inc. + **/ \ No newline at end of file diff --git a/gen/templates/list.tpl b/gen/templates/list.tpl new file mode 100644 index 0000000..666b1c7 --- /dev/null +++ b/gen/templates/list.tpl @@ -0,0 +1,3 @@ +async list(params?: QueryParamsList, options?: ResourcesConfig): Promise> { + return this.resources.list<##__RESOURCE_RESPONSE_CLASS__##>({ type: ##__RESOURCE_CLASS__##.TYPE }, params, options) +} \ No newline at end of file diff --git a/gen/templates/model.tpl b/gen/templates/model.tpl new file mode 100644 index 0000000..5139a1b --- /dev/null +++ b/gen/templates/model.tpl @@ -0,0 +1,4 @@ +interface ##__RESOURCE_MODEL__## extends Resource##__EXTEND_TYPE__## { + ##__RESOURCE_MODEL_FIELDS__## + ##__RESOURCE_MODEL_RELATIONSHIPS__## +} \ No newline at end of file diff --git a/gen/templates/model_empty.tpl b/gen/templates/model_empty.tpl new file mode 100644 index 0000000..0b0b746 --- /dev/null +++ b/gen/templates/model_empty.tpl @@ -0,0 +1 @@ +type ##__RESOURCE_MODEL__## = Resource##__EXTEND_TYPE__## \ No newline at end of file diff --git a/gen/templates/relationship_many.tpl b/gen/templates/relationship_many.tpl new file mode 100644 index 0000000..7423a92 --- /dev/null +++ b/gen/templates/relationship_many.tpl @@ -0,0 +1,4 @@ +async ##__OPERATION_NAME__##(##__RESOURCE_ID__##: string | ##__MODEL_RESOURCE_INTERFACE__##, params?: QueryParamsList, options?: ResourcesConfig): Promise> { + const _##__RESOURCE_ID__## = (##__RESOURCE_ID__## as ##__MODEL_RESOURCE_INTERFACE__##).id || ##__RESOURCE_ID__## as string + return this.resources.fetch<##__RESOURCE_RESPONSE_CLASS__##>({ type: '##__RELATIONSHIP_TYPE__##' }, `##__RELATIONSHIP_PATH__##`, params, options) as unknown as ListResponse<##__RESOURCE_RESPONSE_CLASS__##> +} \ No newline at end of file diff --git a/gen/templates/relationship_one.tpl b/gen/templates/relationship_one.tpl new file mode 100644 index 0000000..a486290 --- /dev/null +++ b/gen/templates/relationship_one.tpl @@ -0,0 +1,4 @@ +async ##__OPERATION_NAME__##(##__RESOURCE_ID__##: string | ##__MODEL_RESOURCE_INTERFACE__##, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise<##__RESOURCE_RESPONSE_CLASS__##> { + const _##__RESOURCE_ID__## = (##__RESOURCE_ID__## as ##__MODEL_RESOURCE_INTERFACE__##).id || ##__RESOURCE_ID__## as string + return this.resources.fetch<##__RESOURCE_RESPONSE_CLASS__##>({ type: '##__RELATIONSHIP_TYPE__##' }, `##__RELATIONSHIP_PATH__##`, params, options) as unknown as ##__RESOURCE_RESPONSE_CLASS__## +} \ No newline at end of file diff --git a/gen/templates/resource.tpl b/gen/templates/resource.tpl new file mode 100644 index 0000000..1627ccf --- /dev/null +++ b/gen/templates/resource.tpl @@ -0,0 +1,41 @@ +import { ##__RESOURCE_MODEL_TYPE__## } from '../resource' +import type { ##__RESOURCE_INTERFACES__##, ##__IMPORT_RESOURCE_COMMON__##, ResourceRel##__RESPONSE_MODELS__## } from '../resource' +##__IMPORT_QUERY_MODELS__## + +##__IMPORT_RESOURCE_MODELS__## + +type ##__MODEL_RESOURCE_INTERFACE__##Type = '##__RESOURCE_TYPE__##' +type ##__MODEL_RESOURCE_INTERFACE__##Rel = ResourceRel & { type: ##__MODEL_RESOURCE_INTERFACE__##Type } +##__RELATIONSHIP_TYPES__## + +##__MODEL_INTERFACES__## + + +class ##__RESOURCE_CLASS__## extends ##__RESOURCE_MODEL_TYPE__##<##__MODEL_RESOURCE_INTERFACE__##> { + + static readonly TYPE: ##__MODEL_RESOURCE_INTERFACE__##Type = '##__RESOURCE_TYPE__##' as const + + ##__RESOURCE_OPERATIONS__## + + + is##__MODEL_RESOURCE_INTERFACE__##(resource: any): resource is ##__MODEL_RESOURCE_INTERFACE__## { + return resource.type && (resource.type === ##__RESOURCE_CLASS__##.TYPE) + } + + + relationship(id: string | ResourceId | null): ##__MODEL_RESOURCE_INTERFACE__##Rel { + return ((id === null) || (typeof id === 'string')) ? { id, type: ##__RESOURCE_CLASS__##.TYPE } : { id: id.id, type: ##__RESOURCE_CLASS__##.TYPE } + } + + + type(): ##__MODEL_RESOURCE_INTERFACE__##Type { + return ##__RESOURCE_CLASS__##.TYPE + } + +} + + +export default ##__RESOURCE_CLASS__## + +export type { ##__EXPORT_RESOURCE_TYPES__##, ##__MODEL_RESOURCE_INTERFACE__##Type } +##__EXPORT_RESOURCE_TYPES_DEF__## \ No newline at end of file diff --git a/gen/templates/retrieve.tpl b/gen/templates/retrieve.tpl new file mode 100644 index 0000000..98f6717 --- /dev/null +++ b/gen/templates/retrieve.tpl @@ -0,0 +1,3 @@ +async retrieve(id: string, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise<##__RESOURCE_RESPONSE_CLASS__##> { + return this.resources.retrieve<##__RESOURCE_RESPONSE_CLASS__##>({ type: ##__RESOURCE_CLASS__##.TYPE, id }, params, options) +} \ No newline at end of file diff --git a/gen/templates/singleton.tpl b/gen/templates/singleton.tpl new file mode 100644 index 0000000..574eca7 --- /dev/null +++ b/gen/templates/singleton.tpl @@ -0,0 +1,3 @@ +async retrieve(params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise<##__RESOURCE_RESPONSE_CLASS__##> { + return this.resources.retrieve<##__RESOURCE_RESPONSE_CLASS__##>({ type: ##__RESOURCE_CLASS__##.TYPE }, params, options) +} \ No newline at end of file diff --git a/gen/templates/singleton_update.tpl b/gen/templates/singleton_update.tpl new file mode 100644 index 0000000..b835dd8 --- /dev/null +++ b/gen/templates/singleton_update.tpl @@ -0,0 +1,4 @@ +async update(resource: ##__RESOURCE_REQUEST_CLASS__##, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise<##__RESOURCE_RESPONSE_CLASS__##> { + const res = await this.retrieve(params, options) // JsonAPI requires id in the request body + return this.resources.update<##__RESOURCE_REQUEST_CLASS__##, ##__RESOURCE_RESPONSE_CLASS__##>({ ...resource, id: res.id, type: ##__RESOURCE_CLASS__##.TYPE }, params, options) +} \ No newline at end of file diff --git a/gen/templates/spec.tpl b/gen/templates/spec.tpl new file mode 100644 index 0000000..d58cd63 --- /dev/null +++ b/gen/templates/spec.tpl @@ -0,0 +1,215 @@ +/** + * ©##__CURRENT_YEAR__## Commerce Layer Inc. + * Source code generated automatically by SDK codegen + **/ + +import { CommerceLayerProvisioningClient, ##__RESOURCE_MODEL__## } from '../../src' +import { isEqual } from 'lodash' +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { getClient, TestData, CommonData, handleError, interceptRequest, checkCommon, checkCommonData, checkCommonParamsList, checkCommonParams, currentAccessToken, randomValue } from '../../test/common' + + + +let clp: CommerceLayerProvisioningClient + + +beforeAll(async () => { clp = await getClient() }) + + +describe('##__RESOURCE_CLASS__## resource', () => { + + const resourceType = '##__RESOURCE_TYPE__##' + + + /* spec.create.start */ + it(resourceType + '.create', async () => { + + const createAttributes = ##__RESOURCE_ATTRIBUTES_CREATE__## + const attributes = { ...createAttributes, reference: TestData.reference } + const params = { fields: { [resourceType]: CommonData.paramsFields } } + const resData = attributes + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('post') + checkCommon(config, resourceType) + checkCommonData(config, resourceType, attributes) + expect(clp[resourceType].is##__RESOURCE_MODEL__##(config.data.data)).toBeTruthy() + return interceptRequest() + }) + + await clp[resourceType].create(resData, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.create.stop */ + + + /* spec.retrieve.start */ + it(resourceType + '.retrieve', async () => { + + const id = TestData.id + const params = { fields: {[resourceType]: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken) + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].retrieve(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.retrieve.stop */ + + + /* spec.update.start */ + it(resourceType + '.update', async () => { + + const attributes = { reference_origin: TestData.reference_origin, metadata: TestData.metadata } + const params = { fields: { [resourceType]: CommonData.paramsFields } } + const resData = { id: TestData.id, ...attributes} + + const intId = clp.addRequestInterceptor((config) => { + if (config.method !== 'get') { + expect(config.method).toBe('patch') + checkCommon(config, resourceType, resData.id, currentAccessToken) + checkCommonData(config, resourceType, attributes, resData.id) + } + return interceptRequest() + }) + + await clp[resourceType].update(resData, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.update.stop */ + + + /* spec.delete.start */ + it(resourceType + '.delete', async () => { + + const id = TestData.id + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('delete') + checkCommon(config, resourceType, id, currentAccessToken) + return interceptRequest() + }) + + await clp[resourceType].delete(id, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.delete.stop */ + + + /* spec.list.start */ + it(resourceType + '.list', async () => { + + const params = CommonData.paramsList + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType) + checkCommonParamsList(config, params) + return interceptRequest() + }) + + await clp[resourceType].list(params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.list.stop */ + + + /* spec.singleton.start */ + it(resourceType + '.singleton', async () => { + + const params = { fields: { [resourceType]: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType) + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].retrieve(params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.singleton.stop */ + + + /* spec.type.start */ + it(resourceType + '.type', async () => { + + const resource = { id: TestData.id, type: resourceType } + expect(clp[resourceType].is##__RESOURCE_MODEL__##(resource)).toBeTruthy() + + const type = clp[resourceType].type() + expect(type).toBe(resourceType) + + }) + /* spec.type.stop */ + + + /* spec.relationship.start */ + it(resourceType + '.relationship', async () => { + + const relId = clp[resourceType].relationship(TestData.id) + expect(isEqual(relId, { id: TestData.id, type: resourceType})) + + const relResId = clp[resourceType].relationship({ id: TestData.id, type: resourceType }) + expect(isEqual(relResId, { id: TestData.id, type: resourceType})) + + }) + /* spec.relationship.stop */ + + + /* spec.parse.start */ + it(resourceType + '.parse', async () => { + + const reference = 'myReferenceId' + + const payload = ` + { + "data": { + "id": "AbcdEfgHiL", + "meta": { + "mode": "test", + "organization_id": "myOrgId" + }, + "type": "${resourceType}", + "links": { + "self": "/api/${resourceType}/AbcdEfgHiL" + }, + "attributes": { + "metadata": {}, + "reference": "${reference}", + "created_at": "2023-10-01T05:53:29.296Z", + "updated_at": "2023-10-10T08:52:13.251Z" + } + } + } + ` + + const res = clp[resourceType].parse(payload) as ##__RESOURCE_MODEL__## + + expect(res.type).toBe(resourceType) + expect(res.reference).toBe(reference) + + }) + /* spec.parse.stop */ + + ##__RELATIONSHIP_SPECS__## + ##__TRIGGER_SPECS__## +}) diff --git a/gen/templates/spec_relationship.tpl b/gen/templates/spec_relationship.tpl new file mode 100644 index 0000000..37be486 --- /dev/null +++ b/gen/templates/spec_relationship.tpl @@ -0,0 +1,19 @@ +/* relationship.##__OPERATION_NAME__## start */ +it(resourceType + '.##__OPERATION_NAME__##', async () => { + + const id = TestData.id + const params = { fields: { ##__RELATIONSHIP_TYPE__##: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, '##__OPERATION_NAME__##') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].##__OPERATION_NAME__##(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + +}) +/* relationship.##__OPERATION_NAME__## stop */ \ No newline at end of file diff --git a/gen/templates/spec_trigger.tpl b/gen/templates/spec_trigger.tpl new file mode 100644 index 0000000..b06ad85 --- /dev/null +++ b/gen/templates/spec_trigger.tpl @@ -0,0 +1,23 @@ +/* trigger.##__OPERATION_NAME__## start */ +it(resourceType + '.##__OPERATION_NAME__##', async () => { + + let triggerAttr = '##__OPERATION_NAME__##' + if (!triggerAttr.startsWith('_')) triggerAttr = `_${triggerAttr}` + + const triggerValue = ##__TRIGGER_VALUE__## + const attributes = { [triggerAttr]: triggerValue } + const id = TestData.id + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('patch') + checkCommon(config, resourceType, id, currentAccessToken) + checkCommonData(config, resourceType, attributes, id) + return interceptRequest() + }) + + await clp[resourceType].##__OPERATION_NAME__##(##__TRIGGER_PARAMS__##, {}, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + +}) +/* trigger.##__OPERATION_NAME__## stop */ \ No newline at end of file diff --git a/gen/templates/trigger.tpl b/gen/templates/trigger.tpl new file mode 100644 index 0000000..e49efcf --- /dev/null +++ b/gen/templates/trigger.tpl @@ -0,0 +1,3 @@ +async ##__OPERATION_NAME__##(id: string | ##__RESOURCE_RESPONSE_CLASS__##,##__TRIGGER_VALUE__## params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise<##__RESOURCE_RESPONSE_CLASS__##> { + return this.resources.update<##__RESOURCE_REQUEST_CLASS__##, ##__RESOURCE_RESPONSE_CLASS__##>({ id: (typeof id === 'string')? id: id.id, type: ##__RESOURCE_CLASS__##.TYPE, ##__OPERATION_NAME__##: ##__TRIGGER_VALUE_TYPE__## }, params, options) +} \ No newline at end of file diff --git a/gen/templates/update.tpl b/gen/templates/update.tpl new file mode 100644 index 0000000..66111db --- /dev/null +++ b/gen/templates/update.tpl @@ -0,0 +1,3 @@ +async update(resource: ##__RESOURCE_REQUEST_CLASS__##, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise<##__RESOURCE_RESPONSE_CLASS__##> { + return this.resources.update<##__RESOURCE_REQUEST_CLASS__##, ##__RESOURCE_RESPONSE_CLASS__##>({ ...resource, type: ##__RESOURCE_CLASS__##.TYPE }, params, options) +} \ No newline at end of file diff --git a/jest.config.js b/jest.config.js new file mode 100644 index 0000000..48d89e2 --- /dev/null +++ b/jest.config.js @@ -0,0 +1,8 @@ +/* global module */ +module.exports = async () => { + return { + verbose: true, + testMatch: ['**/specs/**/*.spec.[jt]s?(x)'], + collectCoverageFrom: ['src/**/{!(ignore-me),}.ts'] + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..ac65226 --- /dev/null +++ b/package.json @@ -0,0 +1,69 @@ +{ + "name": "@commercelayer/provisioning-sdk", + "version": "1.0.0-beta.11", + "main": "lib/cjs/index.js", + "types": "lib/cjs/index.d.ts", + "module": "lib/esm/index.js", + "scripts": { + "clean": "rm -rf ./.nyc_output ./node_modules/.cache ./coverage", + "build": "tsc -b tsconfig.json tsconfig.esm.json --verbose", + "postbuild": "minimize-js -d lib", + "generate": "ts-node gen/generator.ts", + "generate-local": "ts-node gen/generator.ts -- --local", + "lint": "eslint ./src --ext .ts", + "lintspec": "eslint ./specs/resources/ --ext .spec.ts", + "semantic-release": "semantic-release", + "test": "jest", + "test-local": "ts-node test/spot.ts", + "coverage": "jest --coverage" + }, + "keywords": [ + "javascript", + "ecommerce", + "jamstack", + "commercelayer" + ], + "author": "Pierluigi Viti ", + "license": "MIT", + "description": "Commerce Layer Provisioning SDK", + "files": [ + "lib/**/*" + ], + "engines": { + "node": ">=16 || ^14.17" + }, + "dependencies": { + "axios": "1.6.5" + }, + "devDependencies": { + "@babel/preset-env": "^7.23.8", + "@babel/preset-typescript": "^7.23.3", + "@commercelayer/eslint-config-ts": "1.3.0", + "@commercelayer/js-auth": "^4.2.0", + "@semantic-release/changelog": "^6.0.3", + "@semantic-release/git": "^10.0.1", + "@types/debug": "^4.1.12", + "@types/jest": "^29.5.11", + "@types/lodash": "^4.14.202", + "@types/node": "^20.11.5", + "dotenv": "^16.3.2", + "eslint": "^8.56.0", + "inflector-js": "^1.0.1", + "jest": "^29.7.0", + "json-typescript": "^1.1.2", + "jsonapi-typescript": "^0.1.3", + "lodash": "^4.17.21", + "minimize-js": "^1.4.0", + "semantic-release": "^22.0.12", + "ts-node": "^10.9.2", + "typescript": "^5.3.3" + }, + "repository": "github:commercelayer/provisioning-sdk", + "bugs": "https://github.com/commercelayer/provisioning-sdk/issues", + "publishConfig": { + "access": "public" + }, + "resolutions": { + "ansi-regex": "5.0.1" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..e9dce5c --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,6791 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +overrides: + ansi-regex: 5.0.1 + +dependencies: + axios: + specifier: 1.6.5 + version: 1.6.5 + +devDependencies: + '@babel/preset-env': + specifier: ^7.23.8 + version: 7.23.8(@babel/core@7.23.7) + '@babel/preset-typescript': + specifier: ^7.23.3 + version: 7.23.3(@babel/core@7.23.7) + '@commercelayer/eslint-config-ts': + specifier: 1.3.0 + version: 1.3.0(eslint@8.56.0)(typescript@5.3.3) + '@commercelayer/js-auth': + specifier: ^4.2.0 + version: 4.2.0 + '@semantic-release/changelog': + specifier: ^6.0.3 + version: 6.0.3(semantic-release@22.0.12) + '@semantic-release/git': + specifier: ^10.0.1 + version: 10.0.1(semantic-release@22.0.12) + '@types/debug': + specifier: ^4.1.12 + version: 4.1.12 + '@types/jest': + specifier: ^29.5.11 + version: 29.5.11 + '@types/lodash': + specifier: ^4.14.202 + version: 4.14.202 + '@types/node': + specifier: ^20.11.5 + version: 20.11.5 + dotenv: + specifier: ^16.3.2 + version: 16.3.2 + eslint: + specifier: ^8.56.0 + version: 8.56.0 + inflector-js: + specifier: ^1.0.1 + version: 1.0.1 + jest: + specifier: ^29.7.0 + version: 29.7.0(@types/node@20.11.5)(ts-node@10.9.2) + json-typescript: + specifier: ^1.1.2 + version: 1.1.2 + jsonapi-typescript: + specifier: ^0.1.3 + version: 0.1.3 + lodash: + specifier: ^4.17.21 + version: 4.17.21 + minimize-js: + specifier: ^1.4.0 + version: 1.4.0 + semantic-release: + specifier: ^22.0.12 + version: 22.0.12(typescript@5.3.3) + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@20.11.5)(typescript@5.3.3) + typescript: + specifier: ^5.3.3 + version: 5.3.3 + +packages: + + /@aashutoshrathi/word-wrap@1.2.6: + resolution: {integrity: sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==} + engines: {node: '>=0.10.0'} + dev: true + + /@ampproject/remapping@2.2.1: + resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.22 + dev: true + + /@babel/code-frame@7.23.5: + resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/highlight': 7.23.4 + chalk: 2.4.2 + dev: true + + /@babel/compat-data@7.23.5: + resolution: {integrity: sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/core@7.23.7: + resolution: {integrity: sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==} + engines: {node: '>=6.9.0'} + dependencies: + '@ampproject/remapping': 2.2.1 + '@babel/code-frame': 7.23.5 + '@babel/generator': 7.23.6 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.7) + '@babel/helpers': 7.23.8 + '@babel/parser': 7.23.6 + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.7 + '@babel/types': 7.23.6 + convert-source-map: 2.0.0 + debug: 4.3.4 + gensync: 1.0.0-beta.2 + json5: 2.2.3 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/generator@7.23.6: + resolution: {integrity: sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + '@jridgewell/gen-mapping': 0.3.3 + '@jridgewell/trace-mapping': 0.3.22 + jsesc: 2.5.2 + dev: true + + /@babel/helper-annotate-as-pure@7.22.5: + resolution: {integrity: sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-builder-binary-assignment-operator-visitor@7.22.15: + resolution: {integrity: sha512-QkBXwGgaoC2GtGZRoma6kv7Szfv06khvhFav67ZExau2RaXzy8MpHSMO2PNoP2XtmQphJQRHFfg77Bq731Yizw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-compilation-targets@7.23.6: + resolution: {integrity: sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/compat-data': 7.23.5 + '@babel/helper-validator-option': 7.23.5 + browserslist: 4.22.2 + lru-cache: 5.1.1 + semver: 6.3.1 + dev: true + + /@babel/helper-create-class-features-plugin@7.23.7(@babel/core@7.23.7): + resolution: {integrity: sha512-xCoqR/8+BoNnXOY7RVSgv6X+o7pmT5q1d+gGcRlXYkI+9B31glE4jeejhKVpA04O1AtzOt7OSQ6VYKP5FcRl9g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-member-expression-to-functions': 7.23.0 + '@babel/helper-optimise-call-expression': 7.22.5 + '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.7) + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + semver: 6.3.1 + dev: true + + /@babel/helper-create-regexp-features-plugin@7.22.15(@babel/core@7.23.7): + resolution: {integrity: sha512-29FkPLFjn4TPEa3RE7GpW+qbE8tlsu3jntNYNfcGsc49LphF1PQIiD+vMZ1z1xVOKt+93khA9tc2JBs3kBjA7w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-annotate-as-pure': 7.22.5 + regexpu-core: 5.3.2 + semver: 6.3.1 + dev: true + + /@babel/helper-define-polyfill-provider@0.4.4(@babel/core@7.23.7): + resolution: {integrity: sha512-QcJMILQCu2jm5TFPGA3lCpJJTeEP+mqeXooG/NZbg/h5FTFi6V0+99ahlRsW8/kRLyb24LZVCCiclDedhLKcBA==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + debug: 4.3.4 + lodash.debounce: 4.0.8 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-define-polyfill-provider@0.5.0(@babel/core@7.23.7): + resolution: {integrity: sha512-NovQquuQLAQ5HuyjCz7WQP9MjRj7dx++yspwiyUiGl9ZyadHRSql1HZh5ogRd8W8w6YM6EQ/NTB8rgjLt5W65Q==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + debug: 4.3.4 + lodash.debounce: 4.0.8 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/helper-environment-visitor@7.22.20: + resolution: {integrity: sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-function-name@7.23.0: + resolution: {integrity: sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-hoist-variables@7.22.5: + resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-member-expression-to-functions@7.23.0: + resolution: {integrity: sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-module-imports@7.22.15: + resolution: {integrity: sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-simple-access': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/helper-validator-identifier': 7.22.20 + dev: true + + /@babel/helper-optimise-call-expression@7.22.5: + resolution: {integrity: sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-plugin-utils@7.22.5: + resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-remap-async-to-generator@7.22.20(@babel/core@7.23.7): + resolution: {integrity: sha512-pBGyV4uBqOns+0UvhsTO8qgl8hO89PmiDYv+/COyp1aeMcmfrfruz+/nCMFiYyFF/Knn0yfrC85ZzNFjembFTw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-wrap-function': 7.22.20 + dev: true + + /@babel/helper-replace-supers@7.22.20(@babel/core@7.23.7): + resolution: {integrity: sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-member-expression-to-functions': 7.23.0 + '@babel/helper-optimise-call-expression': 7.22.5 + dev: true + + /@babel/helper-simple-access@7.22.5: + resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-skip-transparent-expression-wrappers@7.22.5: + resolution: {integrity: sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-split-export-declaration@7.22.6: + resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/helper-string-parser@7.23.4: + resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-identifier@7.22.20: + resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-validator-option@7.23.5: + resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} + engines: {node: '>=6.9.0'} + dev: true + + /@babel/helper-wrap-function@7.22.20: + resolution: {integrity: sha512-pms/UwkOpnQe/PDAEdV/d7dVCoBbB+R4FvYoHGZz+4VPcg7RtYy2KP7S2lbuWM6FCSgob5wshfGESbC/hzNXZw==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-function-name': 7.23.0 + '@babel/template': 7.22.15 + '@babel/types': 7.23.6 + dev: true + + /@babel/helpers@7.23.8: + resolution: {integrity: sha512-KDqYz4PiOWvDFrdHLPhKtCThtIcKVy6avWD2oG4GEvyQ+XDZwHD4YQd+H2vNMnq2rkdxsDkU82T+Vk8U/WXHRQ==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/template': 7.22.15 + '@babel/traverse': 7.23.7 + '@babel/types': 7.23.6 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/highlight@7.23.4: + resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-validator-identifier': 7.22.20 + chalk: 2.4.2 + js-tokens: 4.0.0 + dev: true + + /@babel/parser@7.23.6: + resolution: {integrity: sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==} + engines: {node: '>=6.0.0'} + hasBin: true + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-iRkKcCqb7iGnq9+3G6rZ+Ciz5VywC4XNRHe57lKM+jOeYAoR0lVqdeeDRfh0tQcTfw/+vBhHn926FmQhLtlFLQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-WwlxbfMNdVEpQjZmK5mhm7oSwD3dS6eU+Iwsi4Knl9wAletWem7kaRsGOG+8UEbRyqxY4SS5zvtfXwX+jMxUwQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.13.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/plugin-transform-optional-chaining': 7.23.4(@babel/core@7.23.7) + dev: true + + /@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly@7.23.7(@babel/core@7.23.7): + resolution: {integrity: sha512-LlRT7HgaifEpQA1ZgLVOIJZZFVPWN5iReq/7/JixwBtwcoeVGDBD53ZV28rrsLYOZs1Y/EHhA8N/Z6aazHR8cw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-proposal-private-property-in-object@7.21.0-placeholder-for-preset-env.2(@babel/core@7.23.7): + resolution: {integrity: sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + dev: true + + /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.23.7): + resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.23.7): + resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.23.7): + resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-class-static-block@7.14.5(@babel/core@7.23.7): + resolution: {integrity: sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-dynamic-import@7.8.3(@babel/core@7.23.7): + resolution: {integrity: sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-export-namespace-from@7.8.3(@babel/core@7.23.7): + resolution: {integrity: sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-import-assertions@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-lPgDSU+SJLK3xmFDTV2ZRQAiM7UuUjGidwBywFavObCiZc1BeAAcMtHJKUya92hPHO+at63JJPLygilZard8jw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-import-attributes@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-pawnE0P9g10xgoP7yKr6CK63K2FMsTE+FZidZO/1PwRdzmAPVs+HS1mAURUsgaoxammTJvULUdIkEK0gOcU2tA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.23.7): + resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.23.7): + resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-jsx@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.23.7): + resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.23.7): + resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.23.7): + resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.23.7): + resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.23.7): + resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.23.7): + resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-private-property-in-object@7.14.5(@babel/core@7.23.7): + resolution: {integrity: sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.23.7): + resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-typescript@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-syntax-unicode-sets-regex@7.18.6(@babel/core@7.23.7): + resolution: {integrity: sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-arrow-functions@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-NzQcQrzaQPkaEwoTm4Mhyl8jI1huEL/WWIEvudjTCMJ9aBZNpsJbMASx7EQECtQQPS/DcnFpo0FIh3LvEO9cxQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-async-generator-functions@7.23.7(@babel/core@7.23.7): + resolution: {integrity: sha512-PdxEpL71bJp1byMG0va5gwQcXHxuEYC/BgI/e88mGTtohbZN28O5Yit0Plkkm/dBzCF/BxmbNcses1RH1T+urA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.23.7) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.23.7) + dev: true + + /@babel/plugin-transform-async-to-generator@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-A7LFsKi4U4fomjqXJlZg/u0ft/n8/7n7lpffUP/ZULx/DtV9SGlNKZolHH6PE8Xl1ngCc0M11OaeZptXVkfKSw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-module-imports': 7.22.15 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-remap-async-to-generator': 7.22.20(@babel/core@7.23.7) + dev: true + + /@babel/plugin-transform-block-scoped-functions@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-vI+0sIaPIO6CNuM9Kk5VmXcMVRiOpDh7w2zZt9GXzmE/9KD70CUEVhvPR/etAeNK/FAEkhxQtXOzVF3EuRL41A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-block-scoping@7.23.4(@babel/core@7.23.7): + resolution: {integrity: sha512-0QqbP6B6HOh7/8iNR4CQU2Th/bbRtBp4KS9vcaZd1fZ0wSh5Fyssg0UCIHwxh+ka+pNDREbVLQnHCMHKZfPwfw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-class-properties@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-uM+AN8yCIjDPccsKGlw271xjJtGii+xQIF/uMPS8H15L12jZTsLfF4o5vNO7d/oUguOyfdikHGc/yi9ge4SGIg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-class-static-block@7.23.4(@babel/core@7.23.7): + resolution: {integrity: sha512-nsWu/1M+ggti1SOALj3hfx5FXzAY06fwPJsUZD4/A5e1bWi46VUIWtD+kOX6/IdhXGsXBWllLFDSnqSCdUNydQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.12.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.23.7) + dev: true + + /@babel/plugin-transform-classes@7.23.8(@babel/core@7.23.7): + resolution: {integrity: sha512-yAYslGsY1bX6Knmg46RjiCiNSwJKv2IUC8qOdYKqMMr0491SXFhcHqOdRDeCRohOOIzwN/90C6mQ9qAKgrP7dg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.7) + '@babel/helper-split-export-declaration': 7.22.6 + globals: 11.12.0 + dev: true + + /@babel/plugin-transform-computed-properties@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-dTj83UVTLw/+nbiHqQSFdwO9CbTtwq1DsDqm3CUEtDrZNET5rT5E6bIdTlOftDTDLMYxvxHNEYO4B9SLl8SLZw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/template': 7.22.15 + dev: true + + /@babel/plugin-transform-destructuring@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-n225npDqjDIr967cMScVKHXJs7rout1q+tt50inyBCPkyZ8KxeI6d+GIbSBTT/w/9WdlWDOej3V9HE5Lgk57gw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-dotall-regex@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-vgnFYDHAKzFaTVp+mneDsIEbnJ2Np/9ng9iviHw3P/KVcgONxpNULEW/51Z/BaFojG2GI2GwwXck5uV1+1NOYQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-duplicate-keys@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-RrqQ+BQmU3Oyav3J+7/myfvRCq7Tbz+kKLLshUmMwNlDHExbGL7ARhajvoBJEvc+fCguPPu887N+3RRXBVKZUA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-dynamic-import@7.23.4(@babel/core@7.23.7): + resolution: {integrity: sha512-V6jIbLhdJK86MaLh4Jpghi8ho5fGzt3imHOBu/x0jlBaPYqDoWz4RDXjmMOfnh+JWNaQleEAByZLV0QzBT4YQQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.23.7) + dev: true + + /@babel/plugin-transform-exponentiation-operator@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-5fhCsl1odX96u7ILKHBj4/Y8vipoqwsJMh4csSA8qFfxrZDEA4Ssku2DyNvMJSmZNOEBT750LfFPbtrnTP90BQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-builder-binary-assignment-operator-visitor': 7.22.15 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-export-namespace-from@7.23.4(@babel/core@7.23.7): + resolution: {integrity: sha512-GzuSBcKkx62dGzZI1WVgTWvkkz84FZO5TC5T8dl/Tht/rAla6Dg/Mz9Yhypg+ezVACf/rgDuQt3kbWEv7LdUDQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.23.7) + dev: true + + /@babel/plugin-transform-for-of@7.23.6(@babel/core@7.23.7): + resolution: {integrity: sha512-aYH4ytZ0qSuBbpfhuofbg/e96oQ7U2w1Aw/UQmKT+1l39uEhUPoFS3fHevDc1G0OvewyDudfMKY1OulczHzWIw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + dev: true + + /@babel/plugin-transform-function-name@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-I1QXp1LxIvt8yLaib49dRW5Okt7Q4oaxao6tFVKS/anCdEOMtYwWVKoiOA1p34GOWIZjUK0E+zCp7+l1pfQyiw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-json-strings@7.23.4(@babel/core@7.23.7): + resolution: {integrity: sha512-81nTOqM1dMwZ/aRXQ59zVubN9wHGqk6UtqRK+/q+ciXmRy8fSolhGVvG09HHRGo4l6fr/c4ZhXUQH0uFW7PZbg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.23.7) + dev: true + + /@babel/plugin-transform-literals@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-wZ0PIXRxnwZvl9AYpqNUxpZ5BiTGrYt7kueGQ+N5FiQ7RCOD4cm8iShd6S6ggfVIWaJf2EMk8eRzAh52RfP4rQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-logical-assignment-operators@7.23.4(@babel/core@7.23.7): + resolution: {integrity: sha512-Mc/ALf1rmZTP4JKKEhUwiORU+vcfarFVLfcFiolKUo6sewoxSEgl36ak5t+4WamRsNr6nzjZXQjM35WsU+9vbg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.23.7) + dev: true + + /@babel/plugin-transform-member-expression-literals@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-sC3LdDBDi5x96LA+Ytekz2ZPk8i/Ck+DEuDbRAll5rknJ5XRTSaPKEYwomLcs1AA8wg9b3KjIQRsnApj+q51Ag==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-modules-amd@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-vJYQGxeKM4t8hYCKVBlZX/gtIY2I7mRGFNcm85sgXGMTBcoV3QdVtdpbcWEbzbfUIUZKwvgFT82mRvaQIebZzw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-modules-commonjs@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-aVS0F65LKsdNOtcz6FRCpE4OgsP2OFnW46qNxNIX9h3wuzaNcSQsJysuMwqSibC98HPrf2vCgtxKNwS0DAlgcA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-simple-access': 7.22.5 + dev: true + + /@babel/plugin-transform-modules-systemjs@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-ZxyKGTkF9xT9YJuKQRo19ewf3pXpopuYQd8cDXqNzc3mUNbOME0RKMoZxviQk74hwzfQsEe66dE92MaZbdHKNQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-identifier': 7.22.20 + dev: true + + /@babel/plugin-transform-modules-umd@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-zHsy9iXX2nIsCBFPud3jKn1IRPWg3Ing1qOZgeKV39m1ZgIdpJqvlWVeiHBZC6ITRG0MfskhYe9cLgntfSFPIg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-named-capturing-groups-regex@7.22.5(@babel/core@7.23.7): + resolution: {integrity: sha512-YgLLKmS3aUBhHaxp5hi1WJTgOUb/NCuDHzGT9z9WTt3YG+CPRhJs6nprbStx6DnWM4dh6gt7SU3sZodbZ08adQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-new-target@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-YJ3xKqtJMAT5/TIZnpAR3I+K+WaDowYbN3xyxI8zxx/Gsypwf9B9h0VB+1Nh6ACAAPRS5NSRje0uVv5i79HYGQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-nullish-coalescing-operator@7.23.4(@babel/core@7.23.7): + resolution: {integrity: sha512-jHE9EVVqHKAQx+VePv5LLGHjmHSJR76vawFPTdlxR/LVJPfOEGxREQwQfjuZEOPTwG92X3LINSh3M40Rv4zpVA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.7) + dev: true + + /@babel/plugin-transform-numeric-separator@7.23.4(@babel/core@7.23.7): + resolution: {integrity: sha512-mps6auzgwjRrwKEZA05cOwuDc9FAzoyFS4ZsG/8F43bTLf/TgkJg7QXOrPO1JO599iA3qgK9MXdMGOEC8O1h6Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.23.7) + dev: true + + /@babel/plugin-transform-object-rest-spread@7.23.4(@babel/core@7.23.7): + resolution: {integrity: sha512-9x9K1YyeQVw0iOXJlIzwm8ltobIIv7j2iLyP2jIhEbqPRQ7ScNgwQufU2I0Gq11VjyG4gI4yMXt2VFags+1N3g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.23.5 + '@babel/core': 7.23.7 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.7) + '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.23.7) + dev: true + + /@babel/plugin-transform-object-super@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-BwQ8q0x2JG+3lxCVFohg+KbQM7plfpBwThdW9A6TMtWwLsbDA01Ek2Zb/AgDN39BiZsExm4qrXxjk+P1/fzGrA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-replace-supers': 7.22.20(@babel/core@7.23.7) + dev: true + + /@babel/plugin-transform-optional-catch-binding@7.23.4(@babel/core@7.23.7): + resolution: {integrity: sha512-XIq8t0rJPHf6Wvmbn9nFxU6ao4c7WhghTR5WyV8SrJfUFzyxhCm4nhC+iAp3HFhbAKLfYpgzhJ6t4XCtVwqO5A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.23.7) + dev: true + + /@babel/plugin-transform-optional-chaining@7.23.4(@babel/core@7.23.7): + resolution: {integrity: sha512-ZU8y5zWOfjM5vZ+asjgAPwDaBjJzgufjES89Rs4Lpq63O300R/kOz30WCLo6BxxX6QVEilwSlpClnG5cZaikTA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.7) + dev: true + + /@babel/plugin-transform-parameters@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-09lMt6UsUb3/34BbECKVbVwrT9bO6lILWln237z7sLaWnMsTi7Yc9fhX5DLpkJzAGfaReXI22wP41SZmnAA3Vw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-private-methods@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-UzqRcRtWsDMTLrRWFvUBDwmw06tCQH9Rl1uAjfh6ijMSmGYQ+fpdB+cnqRC8EMh5tuuxSv0/TejGL+7vyj+50g==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-private-property-in-object@7.23.4(@babel/core@7.23.7): + resolution: {integrity: sha512-9G3K1YqTq3F4Vt88Djx1UZ79PDyj+yKRnUy7cZGSMe+a7jkwD259uKKuUzQlPkGam7R+8RJwh5z4xO27fA1o2A==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.23.7) + dev: true + + /@babel/plugin-transform-property-literals@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-jR3Jn3y7cZp4oEWPFAlRsSWjxKe4PZILGBSd4nis1TsC5qeSpb+nrtihJuDhNI7QHiVbUaiXa0X2RZY3/TI6Nw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-regenerator@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-KP+75h0KghBMcVpuKisx3XTu9Ncut8Q8TuvGO4IhY+9D5DFEckQefOuIsB/gQ2tG71lCke4NMrtIPS8pOj18BQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + regenerator-transform: 0.15.2 + dev: true + + /@babel/plugin-transform-reserved-words@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-QnNTazY54YqgGxwIexMZva9gqbPa15t/x9VS+0fsEFWplwVpXYZivtgl43Z1vMpc1bdPP2PP8siFeVcnFvA3Cg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-shorthand-properties@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-ED2fgqZLmexWiN+YNFX26fx4gh5qHDhn1O2gvEhreLW2iI63Sqm4llRLCXALKrCnbN4Jy0VcMQZl/SAzqug/jg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-spread@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-VvfVYlrlBVu+77xVTOAoxQ6mZbnIq5FM0aGBSFEcIh03qHf+zNqA4DC/3XMUozTg7bZV3e3mZQ0i13VB6v5yUg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-skip-transparent-expression-wrappers': 7.22.5 + dev: true + + /@babel/plugin-transform-sticky-regex@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-HZOyN9g+rtvnOU3Yh7kSxXrKbzgrm5X4GncPY1QOquu7epga5MxKHVpYu2hvQnry/H+JjckSYRb93iNfsioAGg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-template-literals@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-Flok06AYNp7GV2oJPZZcP9vZdszev6vPBkHLwxwSpaIqx75wn6mUd3UFWsSsA0l8nXAKkyCmL/sR02m8RYGeHg==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-typeof-symbol@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-4t15ViVnaFdrPC74be1gXBSMzXk3B4Us9lP7uLRQHTFpV5Dvt33pn+2MyyNxmN3VTTm3oTrZVMUmuw3oBnQ2oQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-typescript@7.23.6(@babel/core@7.23.7): + resolution: {integrity: sha512-6cBG5mBvUu4VUD04OHKnYzbuHNP8huDsD3EDqqpIpsswTDoqHCjLoHb6+QgsV1WsT2nipRqCPgxD3LXnEO7XfA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-annotate-as-pure': 7.22.5 + '@babel/helper-create-class-features-plugin': 7.23.7(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.7) + dev: true + + /@babel/plugin-transform-unicode-escapes@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-OMCUx/bU6ChE3r4+ZdylEqAjaQgHAgipgW8nsCfu5pGqDcFytVd91AwRvUJSBZDz0exPGgnjoqhgRYLRjFZc9Q==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-unicode-property-regex@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-KcLIm+pDZkWZQAFJ9pdfmh89EwVfmNovFBcXko8szpBeF8z68kWIPeKlmSOkT9BXJxs2C0uk+5LxoxIv62MROA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-unicode-regex@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-wMHpNA4x2cIA32b/ci3AfwNgheiva2W0WUKWTK7vBHBhDKfPsc5cFGNWm69WBqpwd86u1qwZ9PWevKqm1A3yAw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/plugin-transform-unicode-sets-regex@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-W7lliA/v9bNR83Qc3q1ip9CQMZ09CcHDbHfbLRDNuAhn1Mvkr1ZNF7hPmztMQvtTGVLJ9m8IZqWsTkXOml8dbw==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-create-regexp-features-plugin': 7.22.15(@babel/core@7.23.7) + '@babel/helper-plugin-utils': 7.22.5 + dev: true + + /@babel/preset-env@7.23.8(@babel/core@7.23.7): + resolution: {integrity: sha512-lFlpmkApLkEP6woIKprO6DO60RImpatTQKtz4sUcDjVcK8M8mQ4sZsuxaTMNOZf0sqAq/ReYW1ZBHnOQwKpLWA==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/compat-data': 7.23.5 + '@babel/core': 7.23.7 + '@babel/helper-compilation-targets': 7.23.6 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-option': 7.23.5 + '@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly': 7.23.7(@babel/core@7.23.7) + '@babel/plugin-proposal-private-property-in-object': 7.21.0-placeholder-for-preset-env.2(@babel/core@7.23.7) + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.23.7) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.23.7) + '@babel/plugin-syntax-class-static-block': 7.14.5(@babel/core@7.23.7) + '@babel/plugin-syntax-dynamic-import': 7.8.3(@babel/core@7.23.7) + '@babel/plugin-syntax-export-namespace-from': 7.8.3(@babel/core@7.23.7) + '@babel/plugin-syntax-import-assertions': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-syntax-import-attributes': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.23.7) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.23.7) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.23.7) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.7) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.23.7) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.7) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.23.7) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.7) + '@babel/plugin-syntax-private-property-in-object': 7.14.5(@babel/core@7.23.7) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.23.7) + '@babel/plugin-syntax-unicode-sets-regex': 7.18.6(@babel/core@7.23.7) + '@babel/plugin-transform-arrow-functions': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-async-generator-functions': 7.23.7(@babel/core@7.23.7) + '@babel/plugin-transform-async-to-generator': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-block-scoped-functions': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-block-scoping': 7.23.4(@babel/core@7.23.7) + '@babel/plugin-transform-class-properties': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-class-static-block': 7.23.4(@babel/core@7.23.7) + '@babel/plugin-transform-classes': 7.23.8(@babel/core@7.23.7) + '@babel/plugin-transform-computed-properties': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-destructuring': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-dotall-regex': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-duplicate-keys': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-dynamic-import': 7.23.4(@babel/core@7.23.7) + '@babel/plugin-transform-exponentiation-operator': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-export-namespace-from': 7.23.4(@babel/core@7.23.7) + '@babel/plugin-transform-for-of': 7.23.6(@babel/core@7.23.7) + '@babel/plugin-transform-function-name': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-json-strings': 7.23.4(@babel/core@7.23.7) + '@babel/plugin-transform-literals': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-logical-assignment-operators': 7.23.4(@babel/core@7.23.7) + '@babel/plugin-transform-member-expression-literals': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-modules-amd': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-modules-systemjs': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-modules-umd': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-named-capturing-groups-regex': 7.22.5(@babel/core@7.23.7) + '@babel/plugin-transform-new-target': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-nullish-coalescing-operator': 7.23.4(@babel/core@7.23.7) + '@babel/plugin-transform-numeric-separator': 7.23.4(@babel/core@7.23.7) + '@babel/plugin-transform-object-rest-spread': 7.23.4(@babel/core@7.23.7) + '@babel/plugin-transform-object-super': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-optional-catch-binding': 7.23.4(@babel/core@7.23.7) + '@babel/plugin-transform-optional-chaining': 7.23.4(@babel/core@7.23.7) + '@babel/plugin-transform-parameters': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-private-methods': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-private-property-in-object': 7.23.4(@babel/core@7.23.7) + '@babel/plugin-transform-property-literals': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-regenerator': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-reserved-words': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-shorthand-properties': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-spread': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-sticky-regex': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-template-literals': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-typeof-symbol': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-unicode-escapes': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-unicode-property-regex': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-unicode-regex': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-unicode-sets-regex': 7.23.3(@babel/core@7.23.7) + '@babel/preset-modules': 0.1.6-no-external-plugins(@babel/core@7.23.7) + babel-plugin-polyfill-corejs2: 0.4.8(@babel/core@7.23.7) + babel-plugin-polyfill-corejs3: 0.8.7(@babel/core@7.23.7) + babel-plugin-polyfill-regenerator: 0.5.5(@babel/core@7.23.7) + core-js-compat: 3.35.1 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/preset-modules@0.1.6-no-external-plugins(@babel/core@7.23.7): + resolution: {integrity: sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==} + peerDependencies: + '@babel/core': ^7.0.0-0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/types': 7.23.6 + esutils: 2.0.3 + dev: true + + /@babel/preset-typescript@7.23.3(@babel/core@7.23.7): + resolution: {integrity: sha512-17oIGVlqz6CchO9RFYn5U6ZpWRZIngayYCtrPRSgANSwC2V1Jb+iP74nVxzzXJte8b8BYxrL1yY96xfhTBrNNQ==} + engines: {node: '>=6.9.0'} + peerDependencies: + '@babel/core': ^7.0.0-0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-plugin-utils': 7.22.5 + '@babel/helper-validator-option': 7.23.5 + '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-modules-commonjs': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-transform-typescript': 7.23.6(@babel/core@7.23.7) + dev: true + + /@babel/regjsgen@0.8.0: + resolution: {integrity: sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==} + dev: true + + /@babel/runtime@7.23.8: + resolution: {integrity: sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw==} + engines: {node: '>=6.9.0'} + dependencies: + regenerator-runtime: 0.14.1 + dev: true + + /@babel/template@7.22.15: + resolution: {integrity: sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.23.5 + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 + dev: true + + /@babel/traverse@7.23.7: + resolution: {integrity: sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/code-frame': 7.23.5 + '@babel/generator': 7.23.6 + '@babel/helper-environment-visitor': 7.22.20 + '@babel/helper-function-name': 7.23.0 + '@babel/helper-hoist-variables': 7.22.5 + '@babel/helper-split-export-declaration': 7.22.6 + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 + debug: 4.3.4 + globals: 11.12.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@babel/types@7.23.6: + resolution: {integrity: sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg==} + engines: {node: '>=6.9.0'} + dependencies: + '@babel/helper-string-parser': 7.23.4 + '@babel/helper-validator-identifier': 7.22.20 + to-fast-properties: 2.0.0 + dev: true + + /@bcoe/v8-coverage@0.2.3: + resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==} + dev: true + + /@colors/colors@1.5.0: + resolution: {integrity: sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==} + engines: {node: '>=0.1.90'} + requiresBuild: true + dev: true + optional: true + + /@commercelayer/eslint-config-ts@1.3.0(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-N0ADyBWf2oPD4q0xVA7T18C+sYfAGmxiLPU8c99k3Mn9nN++gKJxXOL16zClokmfdEYn481nvmQHcmUaKOJYZw==} + peerDependencies: + eslint: '>=8.0' + typescript: '>=5.0' + dependencies: + '@typescript-eslint/eslint-plugin': 6.19.1(@typescript-eslint/parser@6.19.1)(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': 6.19.1(eslint@8.56.0)(typescript@5.3.3) + eslint: 8.56.0 + eslint-config-prettier: 9.1.0(eslint@8.56.0) + eslint-config-standard-with-typescript: 42.0.0(@typescript-eslint/eslint-plugin@6.19.1)(eslint-plugin-import@2.29.1)(eslint-plugin-n@16.6.2)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.1)(eslint@8.56.0) + eslint-plugin-n: 16.6.2(eslint@8.56.0) + eslint-plugin-prettier: 5.1.3(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.2.4) + eslint-plugin-promise: 6.1.1(eslint@8.56.0) + prettier: 3.2.4 + typescript: 5.3.3 + transitivePeerDependencies: + - '@types/eslint' + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /@commercelayer/js-auth@4.2.0: + resolution: {integrity: sha512-KVVi3blZDVKHJCo2DWWbAuhfEGiF3a90OtPHVkjtyeW7n8m5/m2+++5CnMhRZKHvKIS7NpW0XPwoQNb7P8hO4Q==} + engines: {node: '>=18.0.0'} + dev: true + + /@cspotcode/source-map-support@0.8.1: + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + dev: true + + /@esbuild/android-arm64@0.18.20: + resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==} + engines: {node: '>=12'} + cpu: [arm64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-arm@0.18.20: + resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==} + engines: {node: '>=12'} + cpu: [arm] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/android-x64@0.18.20: + resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==} + engines: {node: '>=12'} + cpu: [x64] + os: [android] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-arm64@0.18.20: + resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/darwin-x64@0.18.20: + resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-arm64@0.18.20: + resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==} + engines: {node: '>=12'} + cpu: [arm64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/freebsd-x64@0.18.20: + resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [freebsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm64@0.18.20: + resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==} + engines: {node: '>=12'} + cpu: [arm64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-arm@0.18.20: + resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==} + engines: {node: '>=12'} + cpu: [arm] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ia32@0.18.20: + resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==} + engines: {node: '>=12'} + cpu: [ia32] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-loong64@0.18.20: + resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==} + engines: {node: '>=12'} + cpu: [loong64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-mips64el@0.18.20: + resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==} + engines: {node: '>=12'} + cpu: [mips64el] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-ppc64@0.18.20: + resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==} + engines: {node: '>=12'} + cpu: [ppc64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-riscv64@0.18.20: + resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==} + engines: {node: '>=12'} + cpu: [riscv64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-s390x@0.18.20: + resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==} + engines: {node: '>=12'} + cpu: [s390x] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/linux-x64@0.18.20: + resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==} + engines: {node: '>=12'} + cpu: [x64] + os: [linux] + requiresBuild: true + dev: true + optional: true + + /@esbuild/netbsd-x64@0.18.20: + resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==} + engines: {node: '>=12'} + cpu: [x64] + os: [netbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/openbsd-x64@0.18.20: + resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==} + engines: {node: '>=12'} + cpu: [x64] + os: [openbsd] + requiresBuild: true + dev: true + optional: true + + /@esbuild/sunos-x64@0.18.20: + resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [sunos] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-arm64@0.18.20: + resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==} + engines: {node: '>=12'} + cpu: [arm64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-ia32@0.18.20: + resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==} + engines: {node: '>=12'} + cpu: [ia32] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@esbuild/win32-x64@0.18.20: + resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==} + engines: {node: '>=12'} + cpu: [x64] + os: [win32] + requiresBuild: true + dev: true + optional: true + + /@eslint-community/eslint-utils@4.4.0(eslint@8.56.0): + resolution: {integrity: sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^6.0.0 || ^7.0.0 || >=8.0.0 + dependencies: + eslint: 8.56.0 + eslint-visitor-keys: 3.4.3 + dev: true + + /@eslint-community/regexpp@4.10.0: + resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==} + engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} + dev: true + + /@eslint/eslintrc@2.1.4: + resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + ajv: 6.12.6 + debug: 4.3.4 + espree: 9.6.1 + globals: 13.24.0 + ignore: 5.3.0 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + minimatch: 3.1.2 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - supports-color + dev: true + + /@eslint/js@8.56.0: + resolution: {integrity: sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /@humanwhocodes/config-array@0.11.14: + resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==} + engines: {node: '>=10.10.0'} + dependencies: + '@humanwhocodes/object-schema': 2.0.2 + debug: 4.3.4 + minimatch: 3.1.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@humanwhocodes/module-importer@1.0.1: + resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==} + engines: {node: '>=12.22'} + dev: true + + /@humanwhocodes/object-schema@2.0.2: + resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==} + dev: true + + /@isaacs/cliui@8.0.2: + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + dependencies: + string-width: 5.1.2 + string-width-cjs: /string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: /strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: /wrap-ansi@7.0.0 + dev: true + + /@istanbuljs/load-nyc-config@1.1.0: + resolution: {integrity: sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==} + engines: {node: '>=8'} + dependencies: + camelcase: 5.3.1 + find-up: 4.1.0 + get-package-type: 0.1.0 + js-yaml: 3.14.1 + resolve-from: 5.0.0 + dev: true + + /@istanbuljs/schema@0.1.3: + resolution: {integrity: sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==} + engines: {node: '>=8'} + dev: true + + /@jest/console@29.7.0: + resolution: {integrity: sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/node': 20.11.5 + chalk: 4.1.2 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + dev: true + + /@jest/core@29.7.0(ts-node@10.9.2): + resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.11.5 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@20.11.5)(ts-node@10.9.2) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.5 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + dev: true + + /@jest/environment@29.7.0: + resolution: {integrity: sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.11.5 + jest-mock: 29.7.0 + dev: true + + /@jest/expect-utils@29.7.0: + resolution: {integrity: sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-get-type: 29.6.3 + dev: true + + /@jest/expect@29.7.0: + resolution: {integrity: sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + expect: 29.7.0 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/fake-timers@29.7.0: + resolution: {integrity: sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@sinonjs/fake-timers': 10.3.0 + '@types/node': 20.11.5 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-util: 29.7.0 + dev: true + + /@jest/globals@29.7.0: + resolution: {integrity: sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/types': 29.6.3 + jest-mock: 29.7.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/reporters@29.7.0: + resolution: {integrity: sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@bcoe/v8-coverage': 0.2.3 + '@jest/console': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.22 + '@types/node': 20.11.5 + chalk: 4.1.2 + collect-v8-coverage: 1.0.2 + exit: 0.1.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + istanbul-lib-coverage: 3.2.2 + istanbul-lib-instrument: 6.0.1 + istanbul-lib-report: 3.0.1 + istanbul-lib-source-maps: 4.0.1 + istanbul-reports: 3.1.6 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + jest-worker: 29.7.0 + slash: 3.0.0 + string-length: 4.0.2 + strip-ansi: 6.0.1 + v8-to-istanbul: 9.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/schemas@29.6.3: + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@sinclair/typebox': 0.27.8 + dev: true + + /@jest/source-map@29.6.3: + resolution: {integrity: sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jridgewell/trace-mapping': 0.3.22 + callsites: 3.1.0 + graceful-fs: 4.2.11 + dev: true + + /@jest/test-result@29.7.0: + resolution: {integrity: sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/console': 29.7.0 + '@jest/types': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + collect-v8-coverage: 1.0.2 + dev: true + + /@jest/test-sequencer@29.7.0: + resolution: {integrity: sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/test-result': 29.7.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + slash: 3.0.0 + dev: true + + /@jest/transform@29.7.0: + resolution: {integrity: sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/core': 7.23.7 + '@jest/types': 29.6.3 + '@jridgewell/trace-mapping': 0.3.22 + babel-plugin-istanbul: 6.1.1 + chalk: 4.1.2 + convert-source-map: 2.0.0 + fast-json-stable-stringify: 2.1.0 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + micromatch: 4.0.5 + pirates: 4.0.6 + slash: 3.0.0 + write-file-atomic: 4.0.2 + transitivePeerDependencies: + - supports-color + dev: true + + /@jest/types@29.6.3: + resolution: {integrity: sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.3 + '@types/istanbul-lib-coverage': 2.0.6 + '@types/istanbul-reports': 3.0.4 + '@types/node': 20.11.5 + '@types/yargs': 17.0.32 + chalk: 4.1.2 + dev: true + + /@jridgewell/gen-mapping@0.3.3: + resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} + engines: {node: '>=6.0.0'} + dependencies: + '@jridgewell/set-array': 1.1.2 + '@jridgewell/sourcemap-codec': 1.4.15 + '@jridgewell/trace-mapping': 0.3.22 + dev: true + + /@jridgewell/resolve-uri@3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/set-array@1.1.2: + resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} + engines: {node: '>=6.0.0'} + dev: true + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + dev: true + + /@jridgewell/trace-mapping@0.3.22: + resolution: {integrity: sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@jridgewell/trace-mapping@0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + dev: true + + /@nodelib/fs.scandir@2.1.5: + resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + run-parallel: 1.2.0 + dev: true + + /@nodelib/fs.stat@2.0.5: + resolution: {integrity: sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==} + engines: {node: '>= 8'} + dev: true + + /@nodelib/fs.walk@1.2.8: + resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} + engines: {node: '>= 8'} + dependencies: + '@nodelib/fs.scandir': 2.1.5 + fastq: 1.16.0 + dev: true + + /@octokit/auth-token@4.0.0: + resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} + engines: {node: '>= 18'} + dev: true + + /@octokit/core@5.1.0: + resolution: {integrity: sha512-BDa2VAMLSh3otEiaMJ/3Y36GU4qf6GI+VivQ/P41NC6GHcdxpKlqV0ikSZ5gdQsmS3ojXeRx5vasgNTinF0Q4g==} + engines: {node: '>= 18'} + dependencies: + '@octokit/auth-token': 4.0.0 + '@octokit/graphql': 7.0.2 + '@octokit/request': 8.1.6 + '@octokit/request-error': 5.0.1 + '@octokit/types': 12.4.0 + before-after-hook: 2.2.3 + universal-user-agent: 6.0.1 + dev: true + + /@octokit/endpoint@9.0.4: + resolution: {integrity: sha512-DWPLtr1Kz3tv8L0UvXTDP1fNwM0S+z6EJpRcvH66orY6Eld4XBMCSYsaWp4xIm61jTWxK68BrR7ibO+vSDnZqw==} + engines: {node: '>= 18'} + dependencies: + '@octokit/types': 12.4.0 + universal-user-agent: 6.0.1 + dev: true + + /@octokit/graphql@7.0.2: + resolution: {integrity: sha512-OJ2iGMtj5Tg3s6RaXH22cJcxXRi7Y3EBqbHTBRq+PQAqfaS8f/236fUrWhfSn8P4jovyzqucxme7/vWSSZBX2Q==} + engines: {node: '>= 18'} + dependencies: + '@octokit/request': 8.1.6 + '@octokit/types': 12.4.0 + universal-user-agent: 6.0.1 + dev: true + + /@octokit/openapi-types@19.1.0: + resolution: {integrity: sha512-6G+ywGClliGQwRsjvqVYpklIfa7oRPA0vyhPQG/1Feh+B+wU0vGH1JiJ5T25d3g1JZYBHzR2qefLi9x8Gt+cpw==} + dev: true + + /@octokit/plugin-paginate-rest@9.1.5(@octokit/core@5.1.0): + resolution: {integrity: sha512-WKTQXxK+bu49qzwv4qKbMMRXej1DU2gq017euWyKVudA6MldaSSQuxtz+vGbhxV4CjxpUxjZu6rM2wfc1FiWVg==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '>=5' + dependencies: + '@octokit/core': 5.1.0 + '@octokit/types': 12.4.0 + dev: true + + /@octokit/plugin-retry@6.0.1(@octokit/core@5.1.0): + resolution: {integrity: sha512-SKs+Tz9oj0g4p28qkZwl/topGcb0k0qPNX/i7vBKmDsjoeqnVfFUquqrE/O9oJY7+oLzdCtkiWSXLpLjvl6uog==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '>=5' + dependencies: + '@octokit/core': 5.1.0 + '@octokit/request-error': 5.0.1 + '@octokit/types': 12.4.0 + bottleneck: 2.19.5 + dev: true + + /@octokit/plugin-throttling@8.1.3(@octokit/core@5.1.0): + resolution: {integrity: sha512-pfyqaqpc0EXh5Cn4HX9lWYsZ4gGbjnSmUILeu4u2gnuM50K/wIk9s1Pxt3lVeVwekmITgN/nJdoh43Ka+vye8A==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': ^5.0.0 + dependencies: + '@octokit/core': 5.1.0 + '@octokit/types': 12.4.0 + bottleneck: 2.19.5 + dev: true + + /@octokit/request-error@5.0.1: + resolution: {integrity: sha512-X7pnyTMV7MgtGmiXBwmO6M5kIPrntOXdyKZLigNfQWSEQzVxR4a4vo49vJjTWX70mPndj8KhfT4Dx+2Ng3vnBQ==} + engines: {node: '>= 18'} + dependencies: + '@octokit/types': 12.4.0 + deprecation: 2.3.1 + once: 1.4.0 + dev: true + + /@octokit/request@8.1.6: + resolution: {integrity: sha512-YhPaGml3ncZC1NfXpP3WZ7iliL1ap6tLkAp6MvbK2fTTPytzVUyUesBBogcdMm86uRYO5rHaM1xIWxigWZ17MQ==} + engines: {node: '>= 18'} + dependencies: + '@octokit/endpoint': 9.0.4 + '@octokit/request-error': 5.0.1 + '@octokit/types': 12.4.0 + universal-user-agent: 6.0.1 + dev: true + + /@octokit/types@12.4.0: + resolution: {integrity: sha512-FLWs/AvZllw/AGVs+nJ+ELCDZZJk+kY0zMen118xhL2zD0s1etIUHm1odgjP7epxYU1ln7SZxEUWYop5bhsdgQ==} + dependencies: + '@octokit/openapi-types': 19.1.0 + dev: true + + /@pkgjs/parseargs@0.11.0: + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + requiresBuild: true + dev: true + optional: true + + /@pkgr/core@0.1.1: + resolution: {integrity: sha512-cq8o4cWH0ibXh9VGi5P20Tu9XF/0fFXl9EUinr9QfTM7a7p0oTA4iJRCQWppXR1Pg8dSM0UCItCkPwsk9qWWYA==} + engines: {node: ^12.20.0 || ^14.18.0 || >=16.0.0} + dev: true + + /@pnpm/config.env-replace@1.1.0: + resolution: {integrity: sha512-htyl8TWnKL7K/ESFa1oW2UB5lVDxuF5DpM7tBi6Hu2LNL3mWkIzNLG6N4zoCUP1lCKNxWy/3iu8mS8MvToGd6w==} + engines: {node: '>=12.22.0'} + dev: true + + /@pnpm/network.ca-file@1.0.2: + resolution: {integrity: sha512-YcPQ8a0jwYU9bTdJDpXjMi7Brhkr1mXsXrUJvjqM2mQDgkRiz8jFaQGOdaLxgjtUfQgZhKy/O3cG/YwmgKaxLA==} + engines: {node: '>=12.22.0'} + dependencies: + graceful-fs: 4.2.10 + dev: true + + /@pnpm/npm-conf@2.2.2: + resolution: {integrity: sha512-UA91GwWPhFExt3IizW6bOeY/pQ0BkuNwKjk9iQW9KqxluGCrg4VenZ0/L+2Y0+ZOtme72EVvg6v0zo3AMQRCeA==} + engines: {node: '>=12'} + dependencies: + '@pnpm/config.env-replace': 1.1.0 + '@pnpm/network.ca-file': 1.0.2 + config-chain: 1.1.13 + dev: true + + /@semantic-release/changelog@6.0.3(semantic-release@22.0.12): + resolution: {integrity: sha512-dZuR5qByyfe3Y03TpmCvAxCyTnp7r5XwtHRf/8vD9EAn4ZWbavUX8adMtXYzE86EVh0gyLA7lm5yW4IV30XUag==} + engines: {node: '>=14.17'} + peerDependencies: + semantic-release: '>=18.0.0' + dependencies: + '@semantic-release/error': 3.0.0 + aggregate-error: 3.1.0 + fs-extra: 11.2.0 + lodash: 4.17.21 + semantic-release: 22.0.12(typescript@5.3.3) + dev: true + + /@semantic-release/commit-analyzer@11.1.0(semantic-release@22.0.12): + resolution: {integrity: sha512-cXNTbv3nXR2hlzHjAMgbuiQVtvWHTlwwISt60B+4NZv01y/QRY7p2HcJm8Eh2StzcTJoNnflvKjHH/cjFS7d5g==} + engines: {node: ^18.17 || >=20.6.1} + peerDependencies: + semantic-release: '>=20.1.0' + dependencies: + conventional-changelog-angular: 7.0.0 + conventional-commits-filter: 4.0.0 + conventional-commits-parser: 5.0.0 + debug: 4.3.4 + import-from-esm: 1.3.3 + lodash-es: 4.17.21 + micromatch: 4.0.5 + semantic-release: 22.0.12(typescript@5.3.3) + transitivePeerDependencies: + - supports-color + dev: true + + /@semantic-release/error@3.0.0: + resolution: {integrity: sha512-5hiM4Un+tpl4cKw3lV4UgzJj+SmfNIDCLLw0TepzQxz9ZGV5ixnqkzIVF+3tp0ZHgcMKE+VNGHJjEeyFG2dcSw==} + engines: {node: '>=14.17'} + dev: true + + /@semantic-release/error@4.0.0: + resolution: {integrity: sha512-mgdxrHTLOjOddRVYIYDo0fR3/v61GNN1YGkfbrjuIKg/uMgCd+Qzo3UAXJ+woLQQpos4pl5Esuw5A7AoNlzjUQ==} + engines: {node: '>=18'} + dev: true + + /@semantic-release/git@10.0.1(semantic-release@22.0.12): + resolution: {integrity: sha512-eWrx5KguUcU2wUPaO6sfvZI0wPafUKAMNC18aXY4EnNcrZL86dEmpNVnC9uMpGZkmZJ9EfCVJBQx4pV4EMGT1w==} + engines: {node: '>=14.17'} + peerDependencies: + semantic-release: '>=18.0.0' + dependencies: + '@semantic-release/error': 3.0.0 + aggregate-error: 3.1.0 + debug: 4.3.4 + dir-glob: 3.0.1 + execa: 5.1.1 + lodash: 4.17.21 + micromatch: 4.0.5 + p-reduce: 2.1.0 + semantic-release: 22.0.12(typescript@5.3.3) + transitivePeerDependencies: + - supports-color + dev: true + + /@semantic-release/github@9.2.6(semantic-release@22.0.12): + resolution: {integrity: sha512-shi+Lrf6exeNZF+sBhK+P011LSbhmIAoUEgEY6SsxF8irJ+J2stwI5jkyDQ+4gzYyDImzV6LCKdYB9FXnQRWKA==} + engines: {node: '>=18'} + peerDependencies: + semantic-release: '>=20.1.0' + dependencies: + '@octokit/core': 5.1.0 + '@octokit/plugin-paginate-rest': 9.1.5(@octokit/core@5.1.0) + '@octokit/plugin-retry': 6.0.1(@octokit/core@5.1.0) + '@octokit/plugin-throttling': 8.1.3(@octokit/core@5.1.0) + '@semantic-release/error': 4.0.0 + aggregate-error: 5.0.0 + debug: 4.3.4 + dir-glob: 3.0.1 + globby: 14.0.0 + http-proxy-agent: 7.0.0 + https-proxy-agent: 7.0.2 + issue-parser: 6.0.0 + lodash-es: 4.17.21 + mime: 4.0.1 + p-filter: 4.1.0 + semantic-release: 22.0.12(typescript@5.3.3) + url-join: 5.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /@semantic-release/npm@11.0.2(semantic-release@22.0.12): + resolution: {integrity: sha512-owtf3RjyPvRE63iUKZ5/xO4uqjRpVQDUB9+nnXj0xwfIeM9pRl+cG+zGDzdftR4m3f2s4Wyf3SexW+kF5DFtWA==} + engines: {node: ^18.17 || >=20} + peerDependencies: + semantic-release: '>=20.1.0' + dependencies: + '@semantic-release/error': 4.0.0 + aggregate-error: 5.0.0 + execa: 8.0.1 + fs-extra: 11.2.0 + lodash-es: 4.17.21 + nerf-dart: 1.0.0 + normalize-url: 8.0.0 + npm: 10.3.0 + rc: 1.2.8 + read-pkg: 9.0.1 + registry-auth-token: 5.0.2 + semantic-release: 22.0.12(typescript@5.3.3) + semver: 7.5.4 + tempy: 3.1.0 + dev: true + + /@semantic-release/release-notes-generator@12.1.0(semantic-release@22.0.12): + resolution: {integrity: sha512-g6M9AjUKAZUZnxaJZnouNBeDNTCUrJ5Ltj+VJ60gJeDaRRahcHsry9HW8yKrnKkKNkx5lbWiEP1FPMqVNQz8Kg==} + engines: {node: ^18.17 || >=20.6.1} + peerDependencies: + semantic-release: '>=20.1.0' + dependencies: + conventional-changelog-angular: 7.0.0 + conventional-changelog-writer: 7.0.1 + conventional-commits-filter: 4.0.0 + conventional-commits-parser: 5.0.0 + debug: 4.3.4 + get-stream: 7.0.1 + import-from-esm: 1.3.3 + into-stream: 7.0.0 + lodash-es: 4.17.21 + read-pkg-up: 11.0.0 + semantic-release: 22.0.12(typescript@5.3.3) + transitivePeerDependencies: + - supports-color + dev: true + + /@sinclair/typebox@0.27.8: + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + dev: true + + /@sindresorhus/is@4.6.0: + resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} + engines: {node: '>=10'} + dev: true + + /@sindresorhus/merge-streams@1.0.0: + resolution: {integrity: sha512-rUV5WyJrJLoloD4NDN1V1+LDMDWOa4OTsT4yYJwQNpTU6FWxkxHpL7eu4w+DmiH8x/EAM1otkPE1+LaspIbplw==} + engines: {node: '>=18'} + dev: true + + /@sinonjs/commons@3.0.1: + resolution: {integrity: sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==} + dependencies: + type-detect: 4.0.8 + dev: true + + /@sinonjs/fake-timers@10.3.0: + resolution: {integrity: sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==} + dependencies: + '@sinonjs/commons': 3.0.1 + dev: true + + /@tsconfig/node10@1.0.9: + resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + dev: true + + /@tsconfig/node12@1.0.11: + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + dev: true + + /@tsconfig/node14@1.0.3: + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + dev: true + + /@tsconfig/node16@1.0.4: + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + dev: true + + /@types/babel__core@7.20.5: + resolution: {integrity: sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==} + dependencies: + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 + '@types/babel__generator': 7.6.8 + '@types/babel__template': 7.4.4 + '@types/babel__traverse': 7.20.5 + dev: true + + /@types/babel__generator@7.6.8: + resolution: {integrity: sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@types/babel__template@7.4.4: + resolution: {integrity: sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==} + dependencies: + '@babel/parser': 7.23.6 + '@babel/types': 7.23.6 + dev: true + + /@types/babel__traverse@7.20.5: + resolution: {integrity: sha512-WXCyOcRtH37HAUkpXhUduaxdm82b4GSlyTqajXviN4EfiuPgNYR109xMCKvpl6zPIpua0DGlMEDCq+g8EdoheQ==} + dependencies: + '@babel/types': 7.23.6 + dev: true + + /@types/debug@4.1.12: + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + dependencies: + '@types/ms': 0.7.34 + dev: true + + /@types/graceful-fs@4.1.9: + resolution: {integrity: sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==} + dependencies: + '@types/node': 20.11.5 + dev: true + + /@types/istanbul-lib-coverage@2.0.6: + resolution: {integrity: sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==} + dev: true + + /@types/istanbul-lib-report@3.0.3: + resolution: {integrity: sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==} + dependencies: + '@types/istanbul-lib-coverage': 2.0.6 + dev: true + + /@types/istanbul-reports@3.0.4: + resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + dependencies: + '@types/istanbul-lib-report': 3.0.3 + dev: true + + /@types/jest@29.5.11: + resolution: {integrity: sha512-S2mHmYIVe13vrm6q4kN6fLYYAka15ALQki/vgDC3mIukEOx8WJlv0kQPM+d4w8Gp6u0uSdKND04IlTXBv0rwnQ==} + dependencies: + expect: 29.7.0 + pretty-format: 29.7.0 + dev: true + + /@types/json-schema@7.0.15: + resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} + dev: true + + /@types/json5@0.0.29: + resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + dev: true + + /@types/lodash@4.14.202: + resolution: {integrity: sha512-OvlIYQK9tNneDlS0VN54LLd5uiPCBOp7gS5Z0f1mjoJYBrtStzgmJBxONW3U6OZqdtNzZPmn9BS/7WI7BFFcFQ==} + dev: true + + /@types/ms@0.7.34: + resolution: {integrity: sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==} + dev: true + + /@types/node@20.11.5: + resolution: {integrity: sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==} + dependencies: + undici-types: 5.26.5 + dev: true + + /@types/normalize-package-data@2.4.4: + resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} + dev: true + + /@types/semver@7.5.6: + resolution: {integrity: sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==} + dev: true + + /@types/stack-utils@2.0.3: + resolution: {integrity: sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==} + dev: true + + /@types/yargs-parser@21.0.3: + resolution: {integrity: sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==} + dev: true + + /@types/yargs@17.0.32: + resolution: {integrity: sha512-xQ67Yc/laOG5uMfX/093MRlGGCIBzZMarVa+gfNKJxWAIgykYpVGkBdbqEzGDDfCrVUj6Hiff4mTZ5BA6TmAog==} + dependencies: + '@types/yargs-parser': 21.0.3 + dev: true + + /@typescript-eslint/eslint-plugin@6.19.1(@typescript-eslint/parser@6.19.1)(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-roQScUGFruWod9CEyoV5KlCYrubC/fvG8/1zXuT0WTcxX87GnMMmnksMwSg99lo1xiKrBzw2icsJPMAw1OtKxg==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + '@typescript-eslint/parser': ^6.0.0 || ^6.0.0-alpha + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@eslint-community/regexpp': 4.10.0 + '@typescript-eslint/parser': 6.19.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/scope-manager': 6.19.1 + '@typescript-eslint/type-utils': 6.19.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/utils': 6.19.1(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.19.1 + debug: 4.3.4 + eslint: 8.56.0 + graphemer: 1.4.0 + ignore: 5.3.0 + natural-compare: 1.4.0 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/parser@6.19.1(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-WEfX22ziAh6pRE9jnbkkLGp/4RhTpffr2ZK5bJ18M8mIfA8A+k97U9ZyaXCEJRlmMHh7R9MJZWXp/r73DzINVQ==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/scope-manager': 6.19.1 + '@typescript-eslint/types': 6.19.1 + '@typescript-eslint/typescript-estree': 6.19.1(typescript@5.3.3) + '@typescript-eslint/visitor-keys': 6.19.1 + debug: 4.3.4 + eslint: 8.56.0 + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/scope-manager@6.19.1: + resolution: {integrity: sha512-4CdXYjKf6/6aKNMSly/BP4iCSOpvMmqtDzRtqFyyAae3z5kkqEjKndR5vDHL8rSuMIIWP8u4Mw4VxLyxZW6D5w==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.19.1 + '@typescript-eslint/visitor-keys': 6.19.1 + dev: true + + /@typescript-eslint/type-utils@6.19.1(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-0vdyld3ecfxJuddDjACUvlAeYNrHP/pDeQk2pWBR2ESeEzQhg52DF53AbI9QCBkYE23lgkhLCZNkHn2hEXXYIg==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/typescript-estree': 6.19.1(typescript@5.3.3) + '@typescript-eslint/utils': 6.19.1(eslint@8.56.0)(typescript@5.3.3) + debug: 4.3.4 + eslint: 8.56.0 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/types@6.19.1: + resolution: {integrity: sha512-6+bk6FEtBhvfYvpHsDgAL3uo4BfvnTnoge5LrrCj2eJN8g3IJdLTD4B/jK3Q6vo4Ql/Hoip9I8aB6fF+6RfDqg==} + engines: {node: ^16.0.0 || >=18.0.0} + dev: true + + /@typescript-eslint/typescript-estree@6.19.1(typescript@5.3.3): + resolution: {integrity: sha512-aFdAxuhzBFRWhy+H20nYu19+Km+gFfwNO4TEqyszkMcgBDYQjmPJ61erHxuT2ESJXhlhrO7I5EFIlZ+qGR8oVA==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + typescript: '*' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + '@typescript-eslint/types': 6.19.1 + '@typescript-eslint/visitor-keys': 6.19.1 + debug: 4.3.4 + globby: 11.1.0 + is-glob: 4.0.3 + minimatch: 9.0.3 + semver: 7.5.4 + ts-api-utils: 1.0.3(typescript@5.3.3) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /@typescript-eslint/utils@6.19.1(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-JvjfEZuP5WoMqwh9SPAPDSHSg9FBHHGhjPugSRxu5jMfjvBpq5/sGTD+9M9aQ5sh6iJ8AY/Kk/oUYVEMAPwi7w==} + engines: {node: ^16.0.0 || >=18.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) + '@types/json-schema': 7.0.15 + '@types/semver': 7.5.6 + '@typescript-eslint/scope-manager': 6.19.1 + '@typescript-eslint/types': 6.19.1 + '@typescript-eslint/typescript-estree': 6.19.1(typescript@5.3.3) + eslint: 8.56.0 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /@typescript-eslint/visitor-keys@6.19.1: + resolution: {integrity: sha512-gkdtIO+xSO/SmI0W68DBg4u1KElmIUo3vXzgHyGPs6cxgB0sa3TlptRAAE0hUY1hM6FcDKEv7aIwiTGm76cXfQ==} + engines: {node: ^16.0.0 || >=18.0.0} + dependencies: + '@typescript-eslint/types': 6.19.1 + eslint-visitor-keys: 3.4.3 + dev: true + + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: true + + /JSONStream@1.3.5: + resolution: {integrity: sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==} + hasBin: true + dependencies: + jsonparse: 1.3.1 + through: 2.3.8 + dev: true + + /acorn-jsx@5.3.2(acorn@8.11.3): + resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==} + peerDependencies: + acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 + dependencies: + acorn: 8.11.3 + dev: true + + /acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + dev: true + + /acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + dev: true + + /agent-base@7.1.0: + resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} + engines: {node: '>= 14'} + dependencies: + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /aggregate-error@3.1.0: + resolution: {integrity: sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==} + engines: {node: '>=8'} + dependencies: + clean-stack: 2.2.0 + indent-string: 4.0.0 + dev: true + + /aggregate-error@5.0.0: + resolution: {integrity: sha512-gOsf2YwSlleG6IjRYG2A7k0HmBMEo6qVNk9Bp/EaLgAJT5ngH6PXbqa4ItvnEwCm/velL5jAnQgsHsWnjhGmvw==} + engines: {node: '>=18'} + dependencies: + clean-stack: 5.2.0 + indent-string: 5.0.0 + dev: true + + /ajv@6.12.6: + resolution: {integrity: sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==} + dependencies: + fast-deep-equal: 3.1.3 + fast-json-stable-stringify: 2.1.0 + json-schema-traverse: 0.4.1 + uri-js: 4.4.1 + dev: true + + /ansi-escapes@4.3.2: + resolution: {integrity: sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.21.3 + dev: true + + /ansi-escapes@6.2.0: + resolution: {integrity: sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==} + engines: {node: '>=14.16'} + dependencies: + type-fest: 3.13.1 + dev: true + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: true + + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + + /ansicolors@0.3.2: + resolution: {integrity: sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==} + dev: true + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + dev: true + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: true + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: true + + /argv-formatter@1.0.0: + resolution: {integrity: sha512-F2+Hkm9xFaRg+GkaNnbwXNDV5O6pnCFEmqyhvfC/Ic5LbgOWjJh3L+mN/s91rxVL3znE7DYVpW0GJFT+4YBgWw==} + dev: true + + /array-buffer-byte-length@1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.5 + is-array-buffer: 3.0.2 + dev: true + + /array-ify@1.0.0: + resolution: {integrity: sha512-c5AMf34bKdvPhQ7tBGhqkgKNUzMr4WUs+WDtC2ZUGOUncbxKMTvqxYctiseW3+L4bA8ec+GcZ6/A/FW4m8ukng==} + dev: true + + /array-includes@3.1.7: + resolution: {integrity: sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + is-string: 1.0.7 + dev: true + + /array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + dev: true + + /array.prototype.findlastindex@1.2.3: + resolution: {integrity: sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + get-intrinsic: 1.2.2 + dev: true + + /array.prototype.flat@1.3.2: + resolution: {integrity: sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + dev: true + + /array.prototype.flatmap@1.3.2: + resolution: {integrity: sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-shim-unscopables: 1.0.2 + dev: true + + /arraybuffer.prototype.slice@1.0.2: + resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + is-array-buffer: 3.0.2 + is-shared-array-buffer: 1.0.2 + dev: true + + /asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + dev: false + + /available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: true + + /axios@1.6.5: + resolution: {integrity: sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==} + dependencies: + follow-redirects: 1.15.5 + form-data: 4.0.0 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + dev: false + + /babel-jest@29.7.0(@babel/core@7.23.7): + resolution: {integrity: sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.8.0 + dependencies: + '@babel/core': 7.23.7 + '@jest/transform': 29.7.0 + '@types/babel__core': 7.20.5 + babel-plugin-istanbul: 6.1.1 + babel-preset-jest: 29.6.3(@babel/core@7.23.7) + chalk: 4.1.2 + graceful-fs: 4.2.11 + slash: 3.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-istanbul@6.1.1: + resolution: {integrity: sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==} + engines: {node: '>=8'} + dependencies: + '@babel/helper-plugin-utils': 7.22.5 + '@istanbuljs/load-nyc-config': 1.1.0 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-instrument: 5.2.1 + test-exclude: 6.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-jest-hoist@29.6.3: + resolution: {integrity: sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/template': 7.22.15 + '@babel/types': 7.23.6 + '@types/babel__core': 7.20.5 + '@types/babel__traverse': 7.20.5 + dev: true + + /babel-plugin-polyfill-corejs2@0.4.8(@babel/core@7.23.7): + resolution: {integrity: sha512-OtIuQfafSzpo/LhnJaykc0R/MMnuLSSVjVYy9mHArIZ9qTCSZ6TpWCuEKZYVoN//t8HqBNScHrOtCrIK5IaGLg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/compat-data': 7.23.5 + '@babel/core': 7.23.7 + '@babel/helper-define-polyfill-provider': 0.5.0(@babel/core@7.23.7) + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-corejs3@0.8.7(@babel/core@7.23.7): + resolution: {integrity: sha512-KyDvZYxAzkC0Aj2dAPyDzi2Ym15e5JKZSK+maI7NAwSqofvuFglbSsxE7wUOvTg9oFVnHMzVzBKcqEb4PJgtOA==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-define-polyfill-provider': 0.4.4(@babel/core@7.23.7) + core-js-compat: 3.35.1 + transitivePeerDependencies: + - supports-color + dev: true + + /babel-plugin-polyfill-regenerator@0.5.5(@babel/core@7.23.7): + resolution: {integrity: sha512-OJGYZlhLqBh2DDHeqAxWB1XIvr49CxiJ2gIt61/PU55CQK4Z58OzMqjDe1zwQdQk+rBYsRc+1rJmdajM3gimHg==} + peerDependencies: + '@babel/core': ^7.4.0 || ^8.0.0-0 <8.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/helper-define-polyfill-provider': 0.5.0(@babel/core@7.23.7) + transitivePeerDependencies: + - supports-color + dev: true + + /babel-preset-current-node-syntax@1.0.1(@babel/core@7.23.7): + resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.7 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.23.7) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.23.7) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.23.7) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.23.7) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.23.7) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.23.7) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.7) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.23.7) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.7) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.23.7) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.7) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.23.7) + dev: true + + /babel-preset-jest@29.6.3(@babel/core@7.23.7): + resolution: {integrity: sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@babel/core': ^7.0.0 + dependencies: + '@babel/core': 7.23.7 + babel-plugin-jest-hoist: 29.6.3 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.23.7) + dev: true + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /before-after-hook@2.2.3: + resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} + dev: true + + /bottleneck@2.19.5: + resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==} + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /browserslist@4.22.2: + resolution: {integrity: sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==} + engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} + hasBin: true + dependencies: + caniuse-lite: 1.0.30001579 + electron-to-chromium: 1.4.642 + node-releases: 2.0.14 + update-browserslist-db: 1.0.13(browserslist@4.22.2) + dev: true + + /bser@2.1.1: + resolution: {integrity: sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==} + dependencies: + node-int64: 0.4.0 + dev: true + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: true + + /builtin-modules@3.3.0: + resolution: {integrity: sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==} + engines: {node: '>=6'} + dev: true + + /builtins@5.0.1: + resolution: {integrity: sha512-qwVpFEHNfhYJIzNRBvd2C1kyo6jz3ZSMPyyuR47OPdiKWlbYnZNyDWuyR175qDnAJLiCo5fBBqPb3RiXgWlkOQ==} + dependencies: + semver: 7.5.4 + dev: true + + /call-bind@1.0.5: + resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} + dependencies: + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + set-function-length: 1.2.0 + dev: true + + /callsites@3.1.0: + resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} + engines: {node: '>=6'} + dev: true + + /camelcase@5.3.1: + resolution: {integrity: sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==} + engines: {node: '>=6'} + dev: true + + /camelcase@6.3.0: + resolution: {integrity: sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==} + engines: {node: '>=10'} + dev: true + + /caniuse-lite@1.0.30001579: + resolution: {integrity: sha512-u5AUVkixruKHJjw/pj9wISlcMpgFWzSrczLZbrqBSxukQixmg0SJ5sZTpvaFvxU0HoQKd4yoyAogyrAz9pzJnA==} + dev: true + + /cardinal@2.1.1: + resolution: {integrity: sha512-JSr5eOgoEymtYHBjNWyjrMqet9Am2miJhlfKNdqLp6zoeAh0KN5dRAcxlecj5mAJrmQomgiOBj35xHLrFjqBpw==} + hasBin: true + dependencies: + ansicolors: 0.3.2 + redeyed: 2.1.1 + dev: true + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: true + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /chalk@5.3.0: + resolution: {integrity: sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==} + engines: {node: ^12.17.0 || ^14.13 || >=16.0.0} + dev: true + + /char-regex@1.0.2: + resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} + engines: {node: '>=10'} + dev: true + + /ci-info@3.9.0: + resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} + engines: {node: '>=8'} + dev: true + + /cjs-module-lexer@1.2.3: + resolution: {integrity: sha512-0TNiGstbQmCFwt4akjjBg5pLRTSyj/PkWQ1ZoO2zntmg9yLqSRxwEa4iCfQLGjqhiqBfOJa7W/E8wfGrTDmlZQ==} + dev: true + + /clean-stack@2.2.0: + resolution: {integrity: sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==} + engines: {node: '>=6'} + dev: true + + /clean-stack@5.2.0: + resolution: {integrity: sha512-TyUIUJgdFnCISzG5zu3291TAsE77ddchd0bepon1VVQrKLGKFED4iXFEDQ24mIPdPBbyE16PK3F8MYE1CmcBEQ==} + engines: {node: '>=14.16'} + dependencies: + escape-string-regexp: 5.0.0 + dev: true + + /cli-table3@0.6.3: + resolution: {integrity: sha512-w5Jac5SykAeZJKntOxJCrm63Eg5/4dhMWIcuTbo9rpE+brgaSZo0RuNJZeOyMgsUdhDeojvgyQLmjI+K50ZGyg==} + engines: {node: 10.* || >= 12.*} + dependencies: + string-width: 4.2.3 + optionalDependencies: + '@colors/colors': 1.5.0 + dev: true + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + dev: true + + /collect-v8-coverage@1.0.2: + resolution: {integrity: sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==} + dev: true + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + dependencies: + delayed-stream: 1.0.0 + dev: false + + /commander@11.1.0: + resolution: {integrity: sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==} + engines: {node: '>=16'} + dev: true + + /compare-func@2.0.0: + resolution: {integrity: sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==} + dependencies: + array-ify: 1.0.0 + dot-prop: 5.3.0 + dev: true + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + dev: true + + /conventional-changelog-angular@7.0.0: + resolution: {integrity: sha512-ROjNchA9LgfNMTTFSIWPzebCwOGFdgkEq45EnvvrmSLvCtAw0HSmrCs7/ty+wAeYUZyNay0YMUNYFTRL72PkBQ==} + engines: {node: '>=16'} + dependencies: + compare-func: 2.0.0 + dev: true + + /conventional-changelog-writer@7.0.1: + resolution: {integrity: sha512-Uo+R9neH3r/foIvQ0MKcsXkX642hdm9odUp7TqgFS7BsalTcjzRlIfWZrZR1gbxOozKucaKt5KAbjW8J8xRSmA==} + engines: {node: '>=16'} + hasBin: true + dependencies: + conventional-commits-filter: 4.0.0 + handlebars: 4.7.8 + json-stringify-safe: 5.0.1 + meow: 12.1.1 + semver: 7.5.4 + split2: 4.2.0 + dev: true + + /conventional-commits-filter@4.0.0: + resolution: {integrity: sha512-rnpnibcSOdFcdclpFwWa+pPlZJhXE7l+XK04zxhbWrhgpR96h33QLz8hITTXbcYICxVr3HZFtbtUAQ+4LdBo9A==} + engines: {node: '>=16'} + dev: true + + /conventional-commits-parser@5.0.0: + resolution: {integrity: sha512-ZPMl0ZJbw74iS9LuX9YIAiW8pfM5p3yh2o/NbXHbkFuZzY5jvdi5jFycEOkmBW5H5I7nA+D6f3UcsCLP2vvSEA==} + engines: {node: '>=16'} + hasBin: true + dependencies: + JSONStream: 1.3.5 + is-text-path: 2.0.0 + meow: 12.1.1 + split2: 4.2.0 + dev: true + + /convert-source-map@2.0.0: + resolution: {integrity: sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==} + dev: true + + /core-js-compat@3.35.1: + resolution: {integrity: sha512-sftHa5qUJY3rs9Zht1WEnmkvXputCyDBczPnr7QDgL8n3qrF3CMXY4VPSYtOLLiOUJcah2WNXREd48iOl6mQIw==} + dependencies: + browserslist: 4.22.2 + dev: true + + /core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + dev: true + + /cosmiconfig@8.3.6(typescript@5.3.3): + resolution: {integrity: sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + path-type: 4.0.0 + typescript: 5.3.3 + dev: true + + /create-jest@29.7.0(@types/node@20.11.5)(ts-node@10.9.2): + resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@20.11.5)(ts-node@10.9.2) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: true + + /create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /crypto-random-string@4.0.0: + resolution: {integrity: sha512-x8dy3RnvYdlUcPOjkEHqozhiwzKNSq7GcPuXFbnyMOCHxX8V3OgIg/pYuabl2sbUPfIJaeAQB7PMOK8DFIdoRA==} + engines: {node: '>=12'} + dependencies: + type-fest: 1.4.0 + dev: true + + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + dev: true + + /debug@4.3.4: + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + dev: true + + /dedent@1.5.1: + resolution: {integrity: sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==} + peerDependencies: + babel-plugin-macros: ^3.1.0 + peerDependenciesMeta: + babel-plugin-macros: + optional: true + dev: true + + /deep-extend@0.6.0: + resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} + engines: {node: '>=4.0.0'} + dev: true + + /deep-is@0.1.4: + resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} + dev: true + + /deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + dev: true + + /define-data-property@1.1.1: + resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + dev: true + + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + has-property-descriptors: 1.0.1 + object-keys: 1.1.1 + dev: true + + /delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + dev: false + + /deprecation@2.3.1: + resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} + dev: true + + /detect-newline@3.1.0: + resolution: {integrity: sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==} + engines: {node: '>=8'} + dev: true + + /diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + + /diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + dev: true + + /dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dependencies: + path-type: 4.0.0 + dev: true + + /doctrine@2.1.0: + resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==} + engines: {node: '>=0.10.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /doctrine@3.0.0: + resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==} + engines: {node: '>=6.0.0'} + dependencies: + esutils: 2.0.3 + dev: true + + /dot-prop@5.3.0: + resolution: {integrity: sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==} + engines: {node: '>=8'} + dependencies: + is-obj: 2.0.0 + dev: true + + /dotenv@16.3.2: + resolution: {integrity: sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==} + engines: {node: '>=12'} + dev: true + + /dts-minify@0.3.2: + resolution: {integrity: sha512-X7SlplQ8TjJMNWwbPfD6Q0s+y2EZqImsrQDEvZcFc3QYy9vdwdUpZi+jos0BBT6c8EJn33F+uePHuofwkRCToA==} + dev: true + + /duplexer2@0.1.4: + resolution: {integrity: sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==} + dependencies: + readable-stream: 2.3.8 + dev: true + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true + + /electron-to-chromium@1.4.642: + resolution: {integrity: sha512-M4+u22ZJGpk4RY7tne6W+APkZhnnhmAH48FNl8iEFK2lEgob+U5rUQsIqQhvAwCXYpfd3H20pHK/ENsCvwTbsA==} + dev: true + + /emittery@0.13.1: + resolution: {integrity: sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==} + engines: {node: '>=12'} + dev: true + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + + /emojilib@2.4.0: + resolution: {integrity: sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==} + dev: true + + /env-ci@10.0.0: + resolution: {integrity: sha512-U4xcd/utDYFgMh0yWj07R1H6L5fwhVbmxBCpnL0DbVSDZVnsC82HONw0wxtxNkIAcua3KtbomQvIk5xFZGAQJw==} + engines: {node: ^18.17 || >=20.6.1} + dependencies: + execa: 8.0.1 + java-properties: 1.0.2 + dev: true + + /error-ex@1.3.2: + resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} + dependencies: + is-arrayish: 0.2.1 + dev: true + + /es-abstract@1.22.3: + resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + arraybuffer.prototype.slice: 1.0.2 + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + es-set-tostringtag: 2.0.2 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.2 + get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + internal-slot: 1.0.6 + is-array-buffer: 3.0.2 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-typed-array: 1.1.12 + is-weakref: 1.0.2 + object-inspect: 1.13.1 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.1 + safe-array-concat: 1.1.0 + safe-regex-test: 1.0.2 + string.prototype.trim: 1.2.8 + string.prototype.trimend: 1.0.7 + string.prototype.trimstart: 1.0.7 + typed-array-buffer: 1.0.0 + typed-array-byte-length: 1.0.0 + typed-array-byte-offset: 1.0.0 + typed-array-length: 1.0.4 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.13 + dev: true + + /es-set-tostringtag@2.0.2: + resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + has-tostringtag: 1.0.0 + hasown: 2.0.0 + dev: true + + /es-shim-unscopables@1.0.2: + resolution: {integrity: sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==} + dependencies: + hasown: 2.0.0 + dev: true + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: true + + /esbuild@0.18.20: + resolution: {integrity: sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==} + engines: {node: '>=12'} + hasBin: true + requiresBuild: true + optionalDependencies: + '@esbuild/android-arm': 0.18.20 + '@esbuild/android-arm64': 0.18.20 + '@esbuild/android-x64': 0.18.20 + '@esbuild/darwin-arm64': 0.18.20 + '@esbuild/darwin-x64': 0.18.20 + '@esbuild/freebsd-arm64': 0.18.20 + '@esbuild/freebsd-x64': 0.18.20 + '@esbuild/linux-arm': 0.18.20 + '@esbuild/linux-arm64': 0.18.20 + '@esbuild/linux-ia32': 0.18.20 + '@esbuild/linux-loong64': 0.18.20 + '@esbuild/linux-mips64el': 0.18.20 + '@esbuild/linux-ppc64': 0.18.20 + '@esbuild/linux-riscv64': 0.18.20 + '@esbuild/linux-s390x': 0.18.20 + '@esbuild/linux-x64': 0.18.20 + '@esbuild/netbsd-x64': 0.18.20 + '@esbuild/openbsd-x64': 0.18.20 + '@esbuild/sunos-x64': 0.18.20 + '@esbuild/win32-arm64': 0.18.20 + '@esbuild/win32-ia32': 0.18.20 + '@esbuild/win32-x64': 0.18.20 + dev: true + + /escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: true + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: true + + /escape-string-regexp@2.0.0: + resolution: {integrity: sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==} + engines: {node: '>=8'} + dev: true + + /escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + dev: true + + /escape-string-regexp@5.0.0: + resolution: {integrity: sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==} + engines: {node: '>=12'} + dev: true + + /eslint-compat-utils@0.1.2(eslint@8.56.0): + resolution: {integrity: sha512-Jia4JDldWnFNIru1Ehx1H5s9/yxiRHY/TimCuUc0jNexew3cF1gI6CYZil1ociakfWO3rRqFjl1mskBblB3RYg==} + engines: {node: '>=12'} + peerDependencies: + eslint: '>=6.0.0' + dependencies: + eslint: 8.56.0 + dev: true + + /eslint-config-prettier@9.1.0(eslint@8.56.0): + resolution: {integrity: sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==} + hasBin: true + peerDependencies: + eslint: '>=7.0.0' + dependencies: + eslint: 8.56.0 + dev: true + + /eslint-config-standard-with-typescript@42.0.0(@typescript-eslint/eslint-plugin@6.19.1)(eslint-plugin-import@2.29.1)(eslint-plugin-n@16.6.2)(eslint-plugin-promise@6.1.1)(eslint@8.56.0)(typescript@5.3.3): + resolution: {integrity: sha512-m1/2g/Sicun1uFZOFigJVeOqo9fE7OkMsNtilcpHwdCdcGr21qsGqYiyxYSvvHfJwY7w5OTQH0hxk8sM2N5Ohg==} + peerDependencies: + '@typescript-eslint/eslint-plugin': ^6.4.0 + eslint: ^8.0.1 + eslint-plugin-import: ^2.25.2 + eslint-plugin-n: '^15.0.0 || ^16.0.0 ' + eslint-plugin-promise: ^6.0.0 + typescript: '*' + dependencies: + '@typescript-eslint/eslint-plugin': 6.19.1(@typescript-eslint/parser@6.19.1)(eslint@8.56.0)(typescript@5.3.3) + '@typescript-eslint/parser': 6.19.1(eslint@8.56.0)(typescript@5.3.3) + eslint: 8.56.0 + eslint-config-standard: 17.1.0(eslint-plugin-import@2.29.1)(eslint-plugin-n@16.6.2)(eslint-plugin-promise@6.1.1)(eslint@8.56.0) + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.1)(eslint@8.56.0) + eslint-plugin-n: 16.6.2(eslint@8.56.0) + eslint-plugin-promise: 6.1.1(eslint@8.56.0) + typescript: 5.3.3 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-config-standard@17.1.0(eslint-plugin-import@2.29.1)(eslint-plugin-n@16.6.2)(eslint-plugin-promise@6.1.1)(eslint@8.56.0): + resolution: {integrity: sha512-IwHwmaBNtDK4zDHQukFDW5u/aTb8+meQWZvNFWkiGmbWjD6bqyuSSBxxXKkCftCUzc1zwCH2m/baCNDLGmuO5Q==} + engines: {node: '>=12.0.0'} + peerDependencies: + eslint: ^8.0.1 + eslint-plugin-import: ^2.25.2 + eslint-plugin-n: '^15.0.0 || ^16.0.0 ' + eslint-plugin-promise: ^6.0.0 + dependencies: + eslint: 8.56.0 + eslint-plugin-import: 2.29.1(@typescript-eslint/parser@6.19.1)(eslint@8.56.0) + eslint-plugin-n: 16.6.2(eslint@8.56.0) + eslint-plugin-promise: 6.1.1(eslint@8.56.0) + dev: true + + /eslint-import-resolver-node@0.3.9: + resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} + dependencies: + debug: 3.2.7 + is-core-module: 2.13.1 + resolve: 1.22.8 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-module-utils@2.8.0(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint@8.56.0): + resolution: {integrity: sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: '*' + eslint-import-resolver-node: '*' + eslint-import-resolver-typescript: '*' + eslint-import-resolver-webpack: '*' + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + eslint: + optional: true + eslint-import-resolver-node: + optional: true + eslint-import-resolver-typescript: + optional: true + eslint-import-resolver-webpack: + optional: true + dependencies: + '@typescript-eslint/parser': 6.19.1(eslint@8.56.0)(typescript@5.3.3) + debug: 3.2.7 + eslint: 8.56.0 + eslint-import-resolver-node: 0.3.9 + transitivePeerDependencies: + - supports-color + dev: true + + /eslint-plugin-es-x@7.5.0(eslint@8.56.0): + resolution: {integrity: sha512-ODswlDSO0HJDzXU0XvgZ3lF3lS3XAZEossh15Q2UHjwrJggWeBoKqqEsLTZLXl+dh5eOAozG0zRcYtuE35oTuQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + eslint: '>=8' + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) + '@eslint-community/regexpp': 4.10.0 + eslint: 8.56.0 + eslint-compat-utils: 0.1.2(eslint@8.56.0) + dev: true + + /eslint-plugin-import@2.29.1(@typescript-eslint/parser@6.19.1)(eslint@8.56.0): + resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} + engines: {node: '>=4'} + peerDependencies: + '@typescript-eslint/parser': '*' + eslint: ^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 + peerDependenciesMeta: + '@typescript-eslint/parser': + optional: true + dependencies: + '@typescript-eslint/parser': 6.19.1(eslint@8.56.0)(typescript@5.3.3) + array-includes: 3.1.7 + array.prototype.findlastindex: 1.2.3 + array.prototype.flat: 1.3.2 + array.prototype.flatmap: 1.3.2 + debug: 3.2.7 + doctrine: 2.1.0 + eslint: 8.56.0 + eslint-import-resolver-node: 0.3.9 + eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.19.1)(eslint-import-resolver-node@0.3.9)(eslint@8.56.0) + hasown: 2.0.0 + is-core-module: 2.13.1 + is-glob: 4.0.3 + minimatch: 3.1.2 + object.fromentries: 2.0.7 + object.groupby: 1.0.1 + object.values: 1.1.7 + semver: 6.3.1 + tsconfig-paths: 3.15.0 + transitivePeerDependencies: + - eslint-import-resolver-typescript + - eslint-import-resolver-webpack + - supports-color + dev: true + + /eslint-plugin-n@16.6.2(eslint@8.56.0): + resolution: {integrity: sha512-6TyDmZ1HXoFQXnhCTUjVFULReoBPOAjpuiKELMkeP40yffI/1ZRO+d9ug/VC6fqISo2WkuIBk3cvuRPALaWlOQ==} + engines: {node: '>=16.0.0'} + peerDependencies: + eslint: '>=7.0.0' + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) + builtins: 5.0.1 + eslint: 8.56.0 + eslint-plugin-es-x: 7.5.0(eslint@8.56.0) + get-tsconfig: 4.7.2 + globals: 13.24.0 + ignore: 5.3.0 + is-builtin-module: 3.2.1 + is-core-module: 2.13.1 + minimatch: 3.1.2 + resolve: 1.22.8 + semver: 7.5.4 + dev: true + + /eslint-plugin-prettier@5.1.3(eslint-config-prettier@9.1.0)(eslint@8.56.0)(prettier@3.2.4): + resolution: {integrity: sha512-C9GCVAs4Eq7ZC/XFQHITLiHJxQngdtraXaM+LoUFoFp/lHNl2Zn8f3WQbe9HvTBBQ9YnKFB0/2Ajdqwo5D1EAw==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + '@types/eslint': '>=8.0.0' + eslint: '>=8.0.0' + eslint-config-prettier: '*' + prettier: '>=3.0.0' + peerDependenciesMeta: + '@types/eslint': + optional: true + eslint-config-prettier: + optional: true + dependencies: + eslint: 8.56.0 + eslint-config-prettier: 9.1.0(eslint@8.56.0) + prettier: 3.2.4 + prettier-linter-helpers: 1.0.0 + synckit: 0.8.8 + dev: true + + /eslint-plugin-promise@6.1.1(eslint@8.56.0): + resolution: {integrity: sha512-tjqWDwVZQo7UIPMeDReOpUgHCmCiH+ePnVT+5zVapL0uuHnegBUs2smM13CzOs2Xb5+MHMRFTs9v24yjba4Oig==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + peerDependencies: + eslint: ^7.0.0 || ^8.0.0 + dependencies: + eslint: 8.56.0 + dev: true + + /eslint-scope@7.2.2: + resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + esrecurse: 4.3.0 + estraverse: 5.3.0 + dev: true + + /eslint-visitor-keys@3.4.3: + resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dev: true + + /eslint@8.56.0: + resolution: {integrity: sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + hasBin: true + dependencies: + '@eslint-community/eslint-utils': 4.4.0(eslint@8.56.0) + '@eslint-community/regexpp': 4.10.0 + '@eslint/eslintrc': 2.1.4 + '@eslint/js': 8.56.0 + '@humanwhocodes/config-array': 0.11.14 + '@humanwhocodes/module-importer': 1.0.1 + '@nodelib/fs.walk': 1.2.8 + '@ungap/structured-clone': 1.2.0 + ajv: 6.12.6 + chalk: 4.1.2 + cross-spawn: 7.0.3 + debug: 4.3.4 + doctrine: 3.0.0 + escape-string-regexp: 4.0.0 + eslint-scope: 7.2.2 + eslint-visitor-keys: 3.4.3 + espree: 9.6.1 + esquery: 1.5.0 + esutils: 2.0.3 + fast-deep-equal: 3.1.3 + file-entry-cache: 6.0.1 + find-up: 5.0.0 + glob-parent: 6.0.2 + globals: 13.24.0 + graphemer: 1.4.0 + ignore: 5.3.0 + imurmurhash: 0.1.4 + is-glob: 4.0.3 + is-path-inside: 3.0.3 + js-yaml: 4.1.0 + json-stable-stringify-without-jsonify: 1.0.1 + levn: 0.4.1 + lodash.merge: 4.6.2 + minimatch: 3.1.2 + natural-compare: 1.4.0 + optionator: 0.9.3 + strip-ansi: 6.0.1 + text-table: 0.2.0 + transitivePeerDependencies: + - supports-color + dev: true + + /espree@9.6.1: + resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + acorn: 8.11.3 + acorn-jsx: 5.3.2(acorn@8.11.3) + eslint-visitor-keys: 3.4.3 + dev: true + + /esprima@4.0.1: + resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /esquery@1.5.0: + resolution: {integrity: sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==} + engines: {node: '>=0.10'} + dependencies: + estraverse: 5.3.0 + dev: true + + /esrecurse@4.3.0: + resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} + engines: {node: '>=4.0'} + dependencies: + estraverse: 5.3.0 + dev: true + + /estraverse@5.3.0: + resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} + engines: {node: '>=4.0'} + dev: true + + /esutils@2.0.3: + resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} + engines: {node: '>=0.10.0'} + dev: true + + /execa@5.1.1: + resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} + engines: {node: '>=10'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 6.0.1 + human-signals: 2.1.0 + is-stream: 2.0.1 + merge-stream: 2.0.0 + npm-run-path: 4.0.1 + onetime: 5.1.2 + signal-exit: 3.0.7 + strip-final-newline: 2.0.0 + dev: true + + /execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.2.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + dev: true + + /exit@0.1.2: + resolution: {integrity: sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==} + engines: {node: '>= 0.8.0'} + dev: true + + /expect@29.7.0: + resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/expect-utils': 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + dev: true + + /fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + dev: true + + /fast-diff@1.3.0: + resolution: {integrity: sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==} + dev: true + + /fast-glob@3.3.2: + resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} + engines: {node: '>=8.6.0'} + dependencies: + '@nodelib/fs.stat': 2.0.5 + '@nodelib/fs.walk': 1.2.8 + glob-parent: 5.1.2 + merge2: 1.4.1 + micromatch: 4.0.5 + dev: true + + /fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + dev: true + + /fast-levenshtein@2.0.6: + resolution: {integrity: sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==} + dev: true + + /fastq@1.16.0: + resolution: {integrity: sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA==} + dependencies: + reusify: 1.0.4 + dev: true + + /fb-watchman@2.0.2: + resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + dependencies: + bser: 2.1.1 + dev: true + + /figures@2.0.0: + resolution: {integrity: sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==} + engines: {node: '>=4'} + dependencies: + escape-string-regexp: 1.0.5 + dev: true + + /figures@6.0.1: + resolution: {integrity: sha512-0oY/olScYD4IhQ8u//gCPA4F3mlTn2dacYmiDm/mbDQvpmLjV4uH+zhsQ5IyXRyvqkvtUkXkNdGvg5OFJTCsuQ==} + engines: {node: '>=18'} + dependencies: + is-unicode-supported: 2.0.0 + dev: true + + /file-entry-cache@6.0.1: + resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flat-cache: 3.2.0 + dev: true + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /find-up-simple@1.0.0: + resolution: {integrity: sha512-q7Us7kcjj2VMePAa02hDAF6d+MzsdsAWEwYyOpwUtlerRBkOEPBCRZrAV4XfcSN8fHAgaD0hP7miwoay6DCprw==} + engines: {node: '>=18'} + dev: true + + /find-up@2.1.0: + resolution: {integrity: sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==} + engines: {node: '>=4'} + dependencies: + locate-path: 2.0.0 + dev: true + + /find-up@4.1.0: + resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==} + engines: {node: '>=8'} + dependencies: + locate-path: 5.0.0 + path-exists: 4.0.0 + dev: true + + /find-up@5.0.0: + resolution: {integrity: sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==} + engines: {node: '>=10'} + dependencies: + locate-path: 6.0.0 + path-exists: 4.0.0 + dev: true + + /find-versions@5.1.0: + resolution: {integrity: sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==} + engines: {node: '>=12'} + dependencies: + semver-regex: 4.0.5 + dev: true + + /flat-cache@3.2.0: + resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==} + engines: {node: ^10.12.0 || >=12.0.0} + dependencies: + flatted: 3.2.9 + keyv: 4.5.4 + rimraf: 3.0.2 + dev: true + + /flatted@3.2.9: + resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==} + dev: true + + /follow-redirects@1.15.5: + resolution: {integrity: sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + dev: false + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: true + + /foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + dev: true + + /form-data@4.0.0: + resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} + engines: {node: '>= 6'} + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + mime-types: 2.1.35 + dev: false + + /from2@2.3.0: + resolution: {integrity: sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==} + dependencies: + inherits: 2.0.4 + readable-stream: 2.3.8 + dev: true + + /fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: true + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: true + + /function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + functions-have-names: 1.2.3 + dev: true + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true + + /gensync@1.0.0-beta.2: + resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} + engines: {node: '>=6.9.0'} + dev: true + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + + /get-intrinsic@1.2.2: + resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} + dependencies: + function-bind: 1.1.2 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + dev: true + + /get-package-type@0.1.0: + resolution: {integrity: sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==} + engines: {node: '>=8.0.0'} + dev: true + + /get-stream@6.0.1: + resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} + engines: {node: '>=10'} + dev: true + + /get-stream@7.0.1: + resolution: {integrity: sha512-3M8C1EOFN6r8AMUhwUAACIoXZJEOufDU5+0gFFN5uNs6XYOralD2Pqkl7m046va6x77FwposWXbAhPPIOus7mQ==} + engines: {node: '>=16'} + dev: true + + /get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + dev: true + + /get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + dev: true + + /get-tsconfig@4.7.2: + resolution: {integrity: sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==} + dependencies: + resolve-pkg-maps: 1.0.0 + dev: true + + /git-log-parser@1.2.0: + resolution: {integrity: sha512-rnCVNfkTL8tdNryFuaY0fYiBWEBcgF748O6ZI61rslBvr2o7U65c2/6npCRqH40vuAhtgtDiqLTJjBVdrejCzA==} + dependencies: + argv-formatter: 1.0.0 + spawn-error-forwarder: 1.0.0 + split2: 1.0.0 + stream-combiner2: 1.1.1 + through2: 2.0.5 + traverse: 0.6.8 + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob-parent@6.0.2: + resolution: {integrity: sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==} + engines: {node: '>=10.13.0'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob@10.3.10: + resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + dependencies: + foreground-child: 3.1.1 + jackspeak: 2.3.6 + minimatch: 9.0.3 + minipass: 7.0.4 + path-scurry: 1.10.1 + dev: true + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: true + + /globals@11.12.0: + resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} + engines: {node: '>=4'} + dev: true + + /globals@13.24.0: + resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==} + engines: {node: '>=8'} + dependencies: + type-fest: 0.20.2 + dev: true + + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + dev: true + + /globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.0 + merge2: 1.4.1 + slash: 3.0.0 + dev: true + + /globby@14.0.0: + resolution: {integrity: sha512-/1WM/LNHRAOH9lZta77uGbq0dAEQM+XjNesWwhlERDVenqothRbnzTrL3/LrIoEPPjeUHC3vrS6TwoyxeHs7MQ==} + engines: {node: '>=18'} + dependencies: + '@sindresorhus/merge-streams': 1.0.0 + fast-glob: 3.3.2 + ignore: 5.3.0 + path-type: 5.0.0 + slash: 5.1.0 + unicorn-magic: 0.1.0 + dev: true + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.2 + dev: true + + /graceful-fs@4.2.10: + resolution: {integrity: sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA==} + dev: true + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: true + + /graphemer@1.4.0: + resolution: {integrity: sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==} + dev: true + + /handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.17.4 + dev: true + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /has-property-descriptors@1.0.1: + resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} + dependencies: + get-intrinsic: 1.2.2 + dev: true + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + dev: true + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: true + + /has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: true + + /hook-std@3.0.0: + resolution: {integrity: sha512-jHRQzjSDzMtFy34AGj1DN+vq54WVuhSvKgrHf0OMiFQTwDD4L/qqofVEWjLOBMTn5+lCD3fPg32W9yOfnEJTTw==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /hosted-git-info@7.0.1: + resolution: {integrity: sha512-+K84LB1DYwMHoHSgaOY/Jfhw3ucPmSET5v98Ke/HdNSw4a0UktWzyW1mjhjpuxxTqOOsfWT/7iVshHmVZ4IpOA==} + engines: {node: ^16.14.0 || >=18.0.0} + dependencies: + lru-cache: 10.1.0 + dev: true + + /html-escaper@2.0.2: + resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} + dev: true + + /http-proxy-agent@7.0.0: + resolution: {integrity: sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /https-proxy-agent@7.0.2: + resolution: {integrity: sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4 + transitivePeerDependencies: + - supports-color + dev: true + + /human-signals@2.1.0: + resolution: {integrity: sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==} + engines: {node: '>=10.17.0'} + dev: true + + /human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + dev: true + + /ignore@5.3.0: + resolution: {integrity: sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg==} + engines: {node: '>= 4'} + dev: true + + /import-fresh@3.3.0: + resolution: {integrity: sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==} + engines: {node: '>=6'} + dependencies: + parent-module: 1.0.1 + resolve-from: 4.0.0 + dev: true + + /import-from-esm@1.3.3: + resolution: {integrity: sha512-U3Qt/CyfFpTUv6LOP2jRTLYjphH6zg3okMfHbyqRa/W2w6hr8OsJWVggNlR4jxuojQy81TgTJTxgSkyoteRGMQ==} + engines: {node: '>=16.20'} + dependencies: + debug: 4.3.4 + import-meta-resolve: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /import-local@3.1.0: + resolution: {integrity: sha512-ASB07uLtnDs1o6EHjKpX34BKYDSqnFerfTOJL2HvMqF70LnxpjkzDB8J44oT9pu4AMPkQwf8jl6szgvNd2tRIg==} + engines: {node: '>=8'} + hasBin: true + dependencies: + pkg-dir: 4.2.0 + resolve-cwd: 3.0.0 + dev: true + + /import-meta-resolve@4.0.0: + resolution: {integrity: sha512-okYUR7ZQPH+efeuMJGlq4f8ubUgO50kByRPyt/Cy1Io4PSRsPjxME+YlVaCOx+NIToW7hCsZNFJyTPFFKepRSA==} + dev: true + + /imurmurhash@0.1.4: + resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} + engines: {node: '>=0.8.19'} + dev: true + + /indent-string@4.0.0: + resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} + engines: {node: '>=8'} + dev: true + + /indent-string@5.0.0: + resolution: {integrity: sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==} + engines: {node: '>=12'} + dev: true + + /index-to-position@0.1.2: + resolution: {integrity: sha512-MWDKS3AS1bGCHLBA2VLImJz42f7bJh8wQsTGCzI3j519/CASStoDONUBVz2I/VID0MpiX3SGSnbOD2xUalbE5g==} + engines: {node: '>=18'} + dev: true + + /inflector-js@1.0.1: + resolution: {integrity: sha512-GYvCqr8mGKPoYH+08e76PV8JoIygIVC9Jxw2jA5QjBm/mK+mJqGdzEcs3L5nugnvP03yHajXpBRMRgHx0e770A==} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: true + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: true + + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: true + + /internal-slot@1.0.6: + resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + hasown: 2.0.0 + side-channel: 1.0.4 + dev: true + + /into-stream@7.0.0: + resolution: {integrity: sha512-2dYz766i9HprMBasCMvHMuazJ7u4WzhJwo5kb3iPSiW/iRYV6uPari3zHoqZlnuaR7V1bEiNMxikhp37rdBXbw==} + engines: {node: '>=12'} + dependencies: + from2: 2.3.0 + p-is-promise: 3.0.0 + dev: true + + /is-array-buffer@3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-typed-array: 1.1.12 + dev: true + + /is-arrayish@0.2.1: + resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} + dev: true + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: true + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: true + + /is-builtin-module@3.2.1: + resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==} + engines: {node: '>=6'} + dependencies: + builtin-modules: 3.3.0 + dev: true + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: true + + /is-core-module@2.13.1: + resolution: {integrity: sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==} + dependencies: + hasown: 2.0.0 + dev: true + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-generator-fn@2.1.0: + resolution: {integrity: sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==} + engines: {node: '>=6'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: true + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-obj@2.0.0: + resolution: {integrity: sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==} + engines: {node: '>=8'} + dev: true + + /is-path-inside@3.0.3: + resolution: {integrity: sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==} + engines: {node: '>=8'} + dev: true + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: true + + /is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.5 + dev: true + + /is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + dev: true + + /is-stream@3.0.0: + resolution: {integrity: sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: true + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: true + + /is-text-path@2.0.0: + resolution: {integrity: sha512-+oDTluR6WEjdXEJMnC2z6A4FRwFoYuvShVVEGsS7ewc0UTi2QtAKMDJuL4BDEVt+5T7MjFo12RP8ghOM75oKJw==} + engines: {node: '>=8'} + dependencies: + text-extensions: 2.4.0 + dev: true + + /is-typed-array@1.1.12: + resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.13 + dev: true + + /is-unicode-supported@2.0.0: + resolution: {integrity: sha512-FRdAyx5lusK1iHG0TWpVtk9+1i+GjrzRffhDg4ovQ7mcidMQ6mj+MhKPmvh7Xwyv5gIS06ns49CA7Sqg7lC22Q==} + engines: {node: '>=18'} + dev: true + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.5 + dev: true + + /isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + dev: true + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /issue-parser@6.0.0: + resolution: {integrity: sha512-zKa/Dxq2lGsBIXQ7CUZWTHfvxPC2ej0KfO7fIPqLlHB9J2hJ7rGhZ5rilhuufylr4RXYPzJUeFjKxz305OsNlA==} + engines: {node: '>=10.13'} + dependencies: + lodash.capitalize: 4.2.1 + lodash.escaperegexp: 4.1.2 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.uniqby: 4.7.0 + dev: true + + /istanbul-lib-coverage@3.2.2: + resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} + engines: {node: '>=8'} + dev: true + + /istanbul-lib-instrument@5.2.1: + resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} + engines: {node: '>=8'} + dependencies: + '@babel/core': 7.23.7 + '@babel/parser': 7.23.6 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 6.3.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-instrument@6.0.1: + resolution: {integrity: sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==} + engines: {node: '>=10'} + dependencies: + '@babel/core': 7.23.7 + '@babel/parser': 7.23.6 + '@istanbuljs/schema': 0.1.3 + istanbul-lib-coverage: 3.2.2 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-lib-report@3.0.1: + resolution: {integrity: sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==} + engines: {node: '>=10'} + dependencies: + istanbul-lib-coverage: 3.2.2 + make-dir: 4.0.0 + supports-color: 7.2.0 + dev: true + + /istanbul-lib-source-maps@4.0.1: + resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} + engines: {node: '>=10'} + dependencies: + debug: 4.3.4 + istanbul-lib-coverage: 3.2.2 + source-map: 0.6.1 + transitivePeerDependencies: + - supports-color + dev: true + + /istanbul-reports@3.1.6: + resolution: {integrity: sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg==} + engines: {node: '>=8'} + dependencies: + html-escaper: 2.0.2 + istanbul-lib-report: 3.0.1 + dev: true + + /jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + dev: true + + /java-properties@1.0.2: + resolution: {integrity: sha512-qjdpeo2yKlYTH7nFdK0vbZWuTCesk4o63v5iVOlhMQPfuIZQfW/HI35SjfhA+4qpg36rnFSvUK5b1m+ckIblQQ==} + engines: {node: '>= 0.6.0'} + dev: true + + /jest-changed-files@29.7.0: + resolution: {integrity: sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + execa: 5.1.1 + jest-util: 29.7.0 + p-limit: 3.1.0 + dev: true + + /jest-circus@29.7.0: + resolution: {integrity: sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/expect': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.11.5 + chalk: 4.1.2 + co: 4.6.0 + dedent: 1.5.1 + is-generator-fn: 2.1.0 + jest-each: 29.7.0 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + p-limit: 3.1.0 + pretty-format: 29.7.0 + pure-rand: 6.0.4 + slash: 3.0.0 + stack-utils: 2.0.6 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + dev: true + + /jest-cli@29.7.0(@types/node@20.11.5)(ts-node@10.9.2): + resolution: {integrity: sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.7.0(ts-node@10.9.2) + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0(@types/node@20.11.5)(ts-node@10.9.2) + exit: 0.1.2 + import-local: 3.1.0 + jest-config: 29.7.0(@types/node@20.11.5)(ts-node@10.9.2) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: true + + /jest-config@29.7.0(@types/node@20.11.5)(ts-node@10.9.2): + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.23.7 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.11.5 + babel-jest: 29.7.0(@babel/core@7.23.7) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + ts-node: 10.9.2(@types/node@20.11.5)(typescript@5.3.3) + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + dev: true + + /jest-diff@29.7.0: + resolution: {integrity: sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + diff-sequences: 29.6.3 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + dev: true + + /jest-docblock@29.7.0: + resolution: {integrity: sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + detect-newline: 3.1.0 + dev: true + + /jest-each@29.7.0: + resolution: {integrity: sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + jest-get-type: 29.6.3 + jest-util: 29.7.0 + pretty-format: 29.7.0 + dev: true + + /jest-environment-node@29.7.0: + resolution: {integrity: sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.11.5 + jest-mock: 29.7.0 + jest-util: 29.7.0 + dev: true + + /jest-get-type@29.6.3: + resolution: {integrity: sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + + /jest-haste-map@29.7.0: + resolution: {integrity: sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/graceful-fs': 4.1.9 + '@types/node': 20.11.5 + anymatch: 3.1.3 + fb-watchman: 2.0.2 + graceful-fs: 4.2.11 + jest-regex-util: 29.6.3 + jest-util: 29.7.0 + jest-worker: 29.7.0 + micromatch: 4.0.5 + walker: 1.0.8 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /jest-leak-detector@29.7.0: + resolution: {integrity: sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + dev: true + + /jest-matcher-utils@29.7.0: + resolution: {integrity: sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + pretty-format: 29.7.0 + dev: true + + /jest-message-util@29.7.0: + resolution: {integrity: sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/code-frame': 7.23.5 + '@jest/types': 29.6.3 + '@types/stack-utils': 2.0.3 + chalk: 4.1.2 + graceful-fs: 4.2.11 + micromatch: 4.0.5 + pretty-format: 29.7.0 + slash: 3.0.0 + stack-utils: 2.0.6 + dev: true + + /jest-mock@29.7.0: + resolution: {integrity: sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/node': 20.11.5 + jest-util: 29.7.0 + dev: true + + /jest-pnp-resolver@1.2.3(jest-resolve@29.7.0): + resolution: {integrity: sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==} + engines: {node: '>=6'} + peerDependencies: + jest-resolve: '*' + peerDependenciesMeta: + jest-resolve: + optional: true + dependencies: + jest-resolve: 29.7.0 + dev: true + + /jest-regex-util@29.6.3: + resolution: {integrity: sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + + /jest-resolve-dependencies@29.7.0: + resolution: {integrity: sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + jest-regex-util: 29.6.3 + jest-snapshot: 29.7.0 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-resolve@29.7.0: + resolution: {integrity: sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + chalk: 4.1.2 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-pnp-resolver: 1.2.3(jest-resolve@29.7.0) + jest-util: 29.7.0 + jest-validate: 29.7.0 + resolve: 1.22.8 + resolve.exports: 2.0.2 + slash: 3.0.0 + dev: true + + /jest-runner@29.7.0: + resolution: {integrity: sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/console': 29.7.0 + '@jest/environment': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.11.5 + chalk: 4.1.2 + emittery: 0.13.1 + graceful-fs: 4.2.11 + jest-docblock: 29.7.0 + jest-environment-node: 29.7.0 + jest-haste-map: 29.7.0 + jest-leak-detector: 29.7.0 + jest-message-util: 29.7.0 + jest-resolve: 29.7.0 + jest-runtime: 29.7.0 + jest-util: 29.7.0 + jest-watcher: 29.7.0 + jest-worker: 29.7.0 + p-limit: 3.1.0 + source-map-support: 0.5.13 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-runtime@29.7.0: + resolution: {integrity: sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/environment': 29.7.0 + '@jest/fake-timers': 29.7.0 + '@jest/globals': 29.7.0 + '@jest/source-map': 29.6.3 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.11.5 + chalk: 4.1.2 + cjs-module-lexer: 1.2.3 + collect-v8-coverage: 1.0.2 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-mock: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + slash: 3.0.0 + strip-bom: 4.0.0 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-snapshot@29.7.0: + resolution: {integrity: sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@babel/core': 7.23.7 + '@babel/generator': 7.23.6 + '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.7) + '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.7) + '@babel/types': 7.23.6 + '@jest/expect-utils': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.23.7) + chalk: 4.1.2 + expect: 29.7.0 + graceful-fs: 4.2.11 + jest-diff: 29.7.0 + jest-get-type: 29.6.3 + jest-matcher-utils: 29.7.0 + jest-message-util: 29.7.0 + jest-util: 29.7.0 + natural-compare: 1.4.0 + pretty-format: 29.7.0 + semver: 7.5.4 + transitivePeerDependencies: + - supports-color + dev: true + + /jest-util@29.7.0: + resolution: {integrity: sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + '@types/node': 20.11.5 + chalk: 4.1.2 + ci-info: 3.9.0 + graceful-fs: 4.2.11 + picomatch: 2.3.1 + dev: true + + /jest-validate@29.7.0: + resolution: {integrity: sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/types': 29.6.3 + camelcase: 6.3.0 + chalk: 4.1.2 + jest-get-type: 29.6.3 + leven: 3.1.0 + pretty-format: 29.7.0 + dev: true + + /jest-watcher@29.7.0: + resolution: {integrity: sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.11.5 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + emittery: 0.13.1 + jest-util: 29.7.0 + string-length: 4.0.2 + dev: true + + /jest-worker@29.7.0: + resolution: {integrity: sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@types/node': 20.11.5 + jest-util: 29.7.0 + merge-stream: 2.0.0 + supports-color: 8.1.1 + dev: true + + /jest@29.7.0(@types/node@20.11.5)(ts-node@10.9.2): + resolution: {integrity: sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/core': 29.7.0(ts-node@10.9.2) + '@jest/types': 29.6.3 + import-local: 3.1.0 + jest-cli: 29.7.0(@types/node@20.11.5)(ts-node@10.9.2) + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: true + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: true + + /js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + dev: true + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: true + + /jsesc@0.5.0: + resolution: {integrity: sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==} + hasBin: true + dev: true + + /jsesc@2.5.2: + resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} + engines: {node: '>=4'} + hasBin: true + dev: true + + /json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + dev: true + + /json-parse-better-errors@1.0.2: + resolution: {integrity: sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==} + dev: true + + /json-parse-even-better-errors@2.3.1: + resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + dev: true + + /json-schema-traverse@0.4.1: + resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} + dev: true + + /json-stable-stringify-without-jsonify@1.0.1: + resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} + dev: true + + /json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + dev: true + + /json-typescript@1.1.2: + resolution: {integrity: sha512-Np07MUsYMKbB0nNlw/MMIRjUK7ehO48LA4FsrzrhCfTUxMKbvOBAo0sc0b4nQ80ge9d32sModCunCgoyUojgUA==} + dev: true + + /json5@1.0.2: + resolution: {integrity: sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: true + + /json5@2.2.3: + resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} + engines: {node: '>=6'} + hasBin: true + dev: true + + /jsonapi-typescript@0.1.3: + resolution: {integrity: sha512-uPcPS01GeM+4HIyn18s7l1yD2S3uLZy2TX1UkQffCM0bLb3TMwudXUyVXPHTMZ4vdZT8MqKqN2vjB5PogTAdFQ==} + dependencies: + json-typescript: 1.1.2 + dev: true + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + dev: true + + /jsonparse@1.3.1: + resolution: {integrity: sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==} + engines: {'0': node >= 0.2.0} + dev: true + + /keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + dependencies: + json-buffer: 3.0.1 + dev: true + + /kleur@3.0.3: + resolution: {integrity: sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==} + engines: {node: '>=6'} + dev: true + + /leven@3.1.0: + resolution: {integrity: sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==} + engines: {node: '>=6'} + dev: true + + /levn@0.4.1: + resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /lines-and-columns@1.2.4: + resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + dev: true + + /load-json-file@4.0.0: + resolution: {integrity: sha512-Kx8hMakjX03tiGTLAIdJ+lL0htKnXjEZN6hk/tozf/WOuYGdZBJrZ+rCJRbVCugsjB3jMLn9746NsQIf5VjBMw==} + engines: {node: '>=4'} + dependencies: + graceful-fs: 4.2.11 + parse-json: 4.0.0 + pify: 3.0.0 + strip-bom: 3.0.0 + dev: true + + /locate-path@2.0.0: + resolution: {integrity: sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==} + engines: {node: '>=4'} + dependencies: + p-locate: 2.0.0 + path-exists: 3.0.0 + dev: true + + /locate-path@5.0.0: + resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} + engines: {node: '>=8'} + dependencies: + p-locate: 4.1.0 + dev: true + + /locate-path@6.0.0: + resolution: {integrity: sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==} + engines: {node: '>=10'} + dependencies: + p-locate: 5.0.0 + dev: true + + /lodash-es@4.17.21: + resolution: {integrity: sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==} + dev: true + + /lodash.capitalize@4.2.1: + resolution: {integrity: sha512-kZzYOKspf8XVX5AvmQF94gQW0lejFVgb80G85bU4ZWzoJ6C03PQg3coYAUpSTpQWelrZELd3XWgHzw4Ck5kaIw==} + dev: true + + /lodash.debounce@4.0.8: + resolution: {integrity: sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==} + dev: true + + /lodash.escaperegexp@4.1.2: + resolution: {integrity: sha512-TM9YBvyC84ZxE3rgfefxUWiQKLilstD6k7PTGt6wfbtXF8ixIJLOL3VYyV/z+ZiPLsVxAsKAFVwWlWeb2Y8Yyw==} + dev: true + + /lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + dev: true + + /lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + dev: true + + /lodash.merge@4.6.2: + resolution: {integrity: sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==} + dev: true + + /lodash.uniqby@4.7.0: + resolution: {integrity: sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==} + dev: true + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true + + /lru-cache@10.1.0: + resolution: {integrity: sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==} + engines: {node: 14 || >=16.14} + dev: true + + /lru-cache@5.1.1: + resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} + dependencies: + yallist: 3.1.1 + dev: true + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + dev: true + + /make-dir@4.0.0: + resolution: {integrity: sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==} + engines: {node: '>=10'} + dependencies: + semver: 7.5.4 + dev: true + + /make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + dev: true + + /makeerror@1.0.12: + resolution: {integrity: sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==} + dependencies: + tmpl: 1.0.5 + dev: true + + /marked-terminal@6.2.0(marked@9.1.6): + resolution: {integrity: sha512-ubWhwcBFHnXsjYNsu+Wndpg0zhY4CahSpPlA70PlO0rR9r2sZpkyU+rkCsOWH+KMEkx847UpALON+HWgxowFtw==} + engines: {node: '>=16.0.0'} + peerDependencies: + marked: '>=1 <12' + dependencies: + ansi-escapes: 6.2.0 + cardinal: 2.1.1 + chalk: 5.3.0 + cli-table3: 0.6.3 + marked: 9.1.6 + node-emoji: 2.1.3 + supports-hyperlinks: 3.0.0 + dev: true + + /marked@9.1.6: + resolution: {integrity: sha512-jcByLnIFkd5gSXZmjNvS1TlmRhCXZjIzHYlaGkPlLIekG55JDR2Z4va9tZwCiP+/RDERiNhMOFu01xd6O5ct1Q==} + engines: {node: '>= 16'} + hasBin: true + dev: true + + /meow@12.1.1: + resolution: {integrity: sha512-BhXM0Au22RwUneMPwSCnyhTOizdWoIEPU9sp0Aqa1PnDMR5Wv2FGXYDjuzJEIX+Eo2Rb8xuYe5jrnm5QowQFkw==} + engines: {node: '>=16.10'} + dev: true + + /merge-stream@2.0.0: + resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} + dev: true + + /merge2@1.4.1: + resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} + engines: {node: '>= 8'} + dev: true + + /micromatch@4.0.5: + resolution: {integrity: sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==} + engines: {node: '>=8.6'} + dependencies: + braces: 3.0.2 + picomatch: 2.3.1 + dev: true + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /mime@4.0.1: + resolution: {integrity: sha512-5lZ5tyrIfliMXzFtkYyekWbtRXObT9OWa8IwQ5uxTBDHucNNwniRqo0yInflj+iYi5CBa6qxadGzGarDfuEOxA==} + engines: {node: '>=16'} + hasBin: true + dev: true + + /mimic-fn@2.1.0: + resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} + engines: {node: '>=6'} + dev: true + + /mimic-fn@4.0.0: + resolution: {integrity: sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==} + engines: {node: '>=12'} + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: true + + /minimize-js@1.4.0: + resolution: {integrity: sha512-mfbzIryB+Mdrv8sbBbrco/cKDpV+B+RwZ5zu8HBllsZwTIIPA3kdAxZ5133nDIJSLJp3DKb36rKuntgVuDyMgg==} + hasBin: true + dependencies: + commander: 11.1.0 + dts-minify: 0.3.2 + esbuild: 0.18.20 + glob: 10.3.10 + pretty-bytes: 6.1.1 + progress-barjs: 2.2.1 + tslib: 2.6.2 + dev: true + + /minipass@7.0.4: + resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} + engines: {node: '>=16 || 14 >=14.17'} + dev: true + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + dev: true + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: true + + /natural-compare@1.4.0: + resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} + dev: true + + /neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: true + + /nerf-dart@1.0.0: + resolution: {integrity: sha512-EZSPZB70jiVsivaBLYDCyntd5eH8NTSMOn3rB+HxwdmKThGELLdYv8qVIMWvZEFy9w8ZZpW9h9OB32l1rGtj7g==} + dev: true + + /node-emoji@2.1.3: + resolution: {integrity: sha512-E2WEOVsgs7O16zsURJ/eH8BqhF029wGpEOnv7Urwdo2wmQanOACwJQh0devF9D9RhoZru0+9JXIS0dBXIAz+lA==} + engines: {node: '>=18'} + dependencies: + '@sindresorhus/is': 4.6.0 + char-regex: 1.0.2 + emojilib: 2.4.0 + skin-tone: 2.0.0 + dev: true + + /node-int64@0.4.0: + resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} + dev: true + + /node-releases@2.0.14: + resolution: {integrity: sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==} + dev: true + + /normalize-package-data@6.0.0: + resolution: {integrity: sha512-UL7ELRVxYBHBgYEtZCXjxuD5vPxnmvMGq0jp/dGPKKrN7tfsBh2IY7TlJ15WWwdjRWD3RJbnsygUurTK3xkPkg==} + engines: {node: ^16.14.0 || >=18.0.0} + dependencies: + hosted-git-info: 7.0.1 + is-core-module: 2.13.1 + semver: 7.5.4 + validate-npm-package-license: 3.0.4 + dev: true + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /normalize-url@8.0.0: + resolution: {integrity: sha512-uVFpKhj5MheNBJRTiMZ9pE/7hD1QTeEvugSJW/OmLzAp78PB5O6adfMNTvmfKhXBkvCzC+rqifWcVYpGFwTjnw==} + engines: {node: '>=14.16'} + dev: true + + /npm-run-path@4.0.1: + resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} + engines: {node: '>=8'} + dependencies: + path-key: 3.1.1 + dev: true + + /npm-run-path@5.2.0: + resolution: {integrity: sha512-W4/tgAXFqFA0iL7fk0+uQ3g7wkL8xJmx3XdK0VGb4cHW//eZTtKGvFBBoRKVTpY7n6ze4NL9ly7rgXcHufqXKg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dependencies: + path-key: 4.0.0 + dev: true + + /npm@10.3.0: + resolution: {integrity: sha512-9u5GFc1UqI2DLlGI7QdjkpIaBs3UhTtY8KoCqYJK24gV/j/tByaI4BA4R7RkOc+ASqZMzFPKt4Pj2Z8JcGo//A==} + engines: {node: ^18.17.0 || >=20.5.0} + hasBin: true + dev: true + bundledDependencies: + - '@isaacs/string-locale-compare' + - '@npmcli/arborist' + - '@npmcli/config' + - '@npmcli/fs' + - '@npmcli/map-workspaces' + - '@npmcli/package-json' + - '@npmcli/promise-spawn' + - '@npmcli/run-script' + - '@sigstore/tuf' + - abbrev + - archy + - cacache + - chalk + - ci-info + - cli-columns + - cli-table3 + - columnify + - fastest-levenshtein + - fs-minipass + - glob + - graceful-fs + - hosted-git-info + - ini + - init-package-json + - is-cidr + - json-parse-even-better-errors + - libnpmaccess + - libnpmdiff + - libnpmexec + - libnpmfund + - libnpmhook + - libnpmorg + - libnpmpack + - libnpmpublish + - libnpmsearch + - libnpmteam + - libnpmversion + - make-fetch-happen + - minimatch + - minipass + - minipass-pipeline + - ms + - node-gyp + - nopt + - normalize-package-data + - npm-audit-report + - npm-install-checks + - npm-package-arg + - npm-pick-manifest + - npm-profile + - npm-registry-fetch + - npm-user-validate + - npmlog + - p-map + - pacote + - parse-conflict-json + - proc-log + - qrcode-terminal + - read + - semver + - spdx-expression-parse + - ssri + - strip-ansi + - supports-color + - tar + - text-table + - tiny-relative-date + - treeverse + - validate-npm-package-name + - which + - write-file-atomic + + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + dev: true + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: true + + /object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: true + + /object.fromentries@2.0.7: + resolution: {integrity: sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /object.groupby@1.0.1: + resolution: {integrity: sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + dev: true + + /object.values@1.1.7: + resolution: {integrity: sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: true + + /onetime@5.1.2: + resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} + engines: {node: '>=6'} + dependencies: + mimic-fn: 2.1.0 + dev: true + + /onetime@6.0.0: + resolution: {integrity: sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==} + engines: {node: '>=12'} + dependencies: + mimic-fn: 4.0.0 + dev: true + + /optionator@0.9.3: + resolution: {integrity: sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==} + engines: {node: '>= 0.8.0'} + dependencies: + '@aashutoshrathi/word-wrap': 1.2.6 + deep-is: 0.1.4 + fast-levenshtein: 2.0.6 + levn: 0.4.1 + prelude-ls: 1.2.1 + type-check: 0.4.0 + dev: true + + /p-each-series@3.0.0: + resolution: {integrity: sha512-lastgtAdoH9YaLyDa5i5z64q+kzOcQHsQ5SsZJD3q0VEyI8mq872S3geuNbRUQLVAE9siMfgKrpj7MloKFHruw==} + engines: {node: '>=12'} + dev: true + + /p-filter@4.1.0: + resolution: {integrity: sha512-37/tPdZ3oJwHaS3gNJdenCDB3Tz26i9sjhnguBtvN0vYlRIiDNnvTWkuh+0hETV9rLPdJ3rlL3yVOYPIAnM8rw==} + engines: {node: '>=18'} + dependencies: + p-map: 7.0.1 + dev: true + + /p-is-promise@3.0.0: + resolution: {integrity: sha512-Wo8VsW4IRQSKVXsJCn7TomUaVtyfjVDn3nUP7kE967BQk0CwFpdbZs0X0uk5sW9mkBa9eNM7hCMaG93WUAwxYQ==} + engines: {node: '>=8'} + dev: true + + /p-limit@1.3.0: + resolution: {integrity: sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==} + engines: {node: '>=4'} + dependencies: + p-try: 1.0.0 + dev: true + + /p-limit@2.3.0: + resolution: {integrity: sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==} + engines: {node: '>=6'} + dependencies: + p-try: 2.2.0 + dev: true + + /p-limit@3.1.0: + resolution: {integrity: sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==} + engines: {node: '>=10'} + dependencies: + yocto-queue: 0.1.0 + dev: true + + /p-locate@2.0.0: + resolution: {integrity: sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==} + engines: {node: '>=4'} + dependencies: + p-limit: 1.3.0 + dev: true + + /p-locate@4.1.0: + resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} + engines: {node: '>=8'} + dependencies: + p-limit: 2.3.0 + dev: true + + /p-locate@5.0.0: + resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} + engines: {node: '>=10'} + dependencies: + p-limit: 3.1.0 + dev: true + + /p-map@7.0.1: + resolution: {integrity: sha512-2wnaR0XL/FDOj+TgpDuRb2KTjLnu3Fma6b1ZUwGY7LcqenMcvP/YFpjpbPKY6WVGsbuJZRuoUz8iPrt8ORnAFw==} + engines: {node: '>=18'} + dev: true + + /p-reduce@2.1.0: + resolution: {integrity: sha512-2USApvnsutq8uoxZBGbbWM0JIYLiEMJ9RlaN7fAzVNb9OZN0SHjjTTfIcb667XynS5Y1VhwDJVDa72TnPzAYWw==} + engines: {node: '>=8'} + dev: true + + /p-reduce@3.0.0: + resolution: {integrity: sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==} + engines: {node: '>=12'} + dev: true + + /p-try@1.0.0: + resolution: {integrity: sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==} + engines: {node: '>=4'} + dev: true + + /p-try@2.2.0: + resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} + engines: {node: '>=6'} + dev: true + + /parent-module@1.0.1: + resolution: {integrity: sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==} + engines: {node: '>=6'} + dependencies: + callsites: 3.1.0 + dev: true + + /parse-json@4.0.0: + resolution: {integrity: sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==} + engines: {node: '>=4'} + dependencies: + error-ex: 1.3.2 + json-parse-better-errors: 1.0.2 + dev: true + + /parse-json@5.2.0: + resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} + engines: {node: '>=8'} + dependencies: + '@babel/code-frame': 7.23.5 + error-ex: 1.3.2 + json-parse-even-better-errors: 2.3.1 + lines-and-columns: 1.2.4 + dev: true + + /parse-json@8.1.0: + resolution: {integrity: sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA==} + engines: {node: '>=18'} + dependencies: + '@babel/code-frame': 7.23.5 + index-to-position: 0.1.2 + type-fest: 4.10.0 + dev: true + + /path-exists@3.0.0: + resolution: {integrity: sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==} + engines: {node: '>=4'} + dev: true + + /path-exists@4.0.0: + resolution: {integrity: sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==} + engines: {node: '>=8'} + dev: true + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-key@4.0.0: + resolution: {integrity: sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==} + engines: {node: '>=12'} + dev: true + + /path-parse@1.0.7: + resolution: {integrity: sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==} + dev: true + + /path-scurry@1.10.1: + resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + lru-cache: 10.1.0 + minipass: 7.0.4 + dev: true + + /path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + dev: true + + /path-type@5.0.0: + resolution: {integrity: sha512-5HviZNaZcfqP95rwpv+1HDgUamezbqdSYTyzjTvwtJSnIH+3vnbmWsItli8OFEndS984VT55M3jduxZbX351gg==} + engines: {node: '>=12'} + dev: true + + /picocolors@1.0.0: + resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} + dev: true + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pify@3.0.0: + resolution: {integrity: sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==} + engines: {node: '>=4'} + dev: true + + /pirates@4.0.6: + resolution: {integrity: sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==} + engines: {node: '>= 6'} + dev: true + + /pkg-conf@2.1.0: + resolution: {integrity: sha512-C+VUP+8jis7EsQZIhDYmS5qlNtjv2yP4SNtjXK9AP1ZcTRlnSfuumaTnRfYZnYgUUYVIKqL0fRvmUGDV2fmp6g==} + engines: {node: '>=4'} + dependencies: + find-up: 2.1.0 + load-json-file: 4.0.0 + dev: true + + /pkg-dir@4.2.0: + resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} + engines: {node: '>=8'} + dependencies: + find-up: 4.1.0 + dev: true + + /prelude-ls@1.2.1: + resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} + engines: {node: '>= 0.8.0'} + dev: true + + /prettier-linter-helpers@1.0.0: + resolution: {integrity: sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==} + engines: {node: '>=6.0.0'} + dependencies: + fast-diff: 1.3.0 + dev: true + + /prettier@3.2.4: + resolution: {integrity: sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /pretty-bytes@6.1.1: + resolution: {integrity: sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==} + engines: {node: ^14.13.1 || >=16.0.0} + dev: true + + /pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.2.0 + dev: true + + /process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + dev: true + + /progress-barjs@2.2.1: + resolution: {integrity: sha512-pgNtlw+gZ/nqQJDYKUbAnyhZPdyiBoxB3gzXcmF7Cl2JhD8I87Z501T3rr97OHoSzx3JFfNcY9ANiAVPF4qPxA==} + dev: true + + /prompts@2.4.2: + resolution: {integrity: sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==} + engines: {node: '>= 6'} + dependencies: + kleur: 3.0.3 + sisteransi: 1.0.5 + dev: true + + /proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + dev: true + + /proxy-from-env@1.1.0: + resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + dev: false + + /punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + dev: true + + /pure-rand@6.0.4: + resolution: {integrity: sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==} + dev: true + + /queue-microtask@1.2.3: + resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + dev: true + + /rc@1.2.8: + resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} + hasBin: true + dependencies: + deep-extend: 0.6.0 + ini: 1.3.8 + minimist: 1.2.8 + strip-json-comments: 2.0.1 + dev: true + + /react-is@18.2.0: + resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + dev: true + + /read-pkg-up@11.0.0: + resolution: {integrity: sha512-LOVbvF1Q0SZdjClSefZ0Nz5z8u+tIE7mV5NibzmE9VYmDe9CaBbAVtz1veOSZbofrdsilxuDAYnFenukZVp8/Q==} + engines: {node: '>=18'} + deprecated: Renamed to read-package-up + dependencies: + find-up-simple: 1.0.0 + read-pkg: 9.0.1 + type-fest: 4.10.0 + dev: true + + /read-pkg@9.0.1: + resolution: {integrity: sha512-9viLL4/n1BJUCT1NXVTdS1jtm80yDEgR5T4yCelII49Mbj0v1rZdKqj7zCiYdbB0CuCgdrvHcNogAKTFPBocFA==} + engines: {node: '>=18'} + dependencies: + '@types/normalize-package-data': 2.4.4 + normalize-package-data: 6.0.0 + parse-json: 8.1.0 + type-fest: 4.10.0 + unicorn-magic: 0.1.0 + dev: true + + /readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + dev: true + + /redeyed@2.1.1: + resolution: {integrity: sha512-FNpGGo1DycYAdnrKFxCMmKYgo/mILAqtRYbkdQD8Ep/Hk2PQ5+aEAEx+IU713RTDmuBaH0c8P5ZozurNu5ObRQ==} + dependencies: + esprima: 4.0.1 + dev: true + + /regenerate-unicode-properties@10.1.1: + resolution: {integrity: sha512-X007RyZLsCJVVrjgEFVpLUTZwyOZk3oiL75ZcuYjlIWd6rNJtOjkBwQc5AsRrpbKVkxN6sklw/k/9m2jJYOf8Q==} + engines: {node: '>=4'} + dependencies: + regenerate: 1.4.2 + dev: true + + /regenerate@1.4.2: + resolution: {integrity: sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==} + dev: true + + /regenerator-runtime@0.14.1: + resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} + dev: true + + /regenerator-transform@0.15.2: + resolution: {integrity: sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==} + dependencies: + '@babel/runtime': 7.23.8 + dev: true + + /regexp.prototype.flags@1.5.1: + resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + set-function-name: 2.0.1 + dev: true + + /regexpu-core@5.3.2: + resolution: {integrity: sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==} + engines: {node: '>=4'} + dependencies: + '@babel/regjsgen': 0.8.0 + regenerate: 1.4.2 + regenerate-unicode-properties: 10.1.1 + regjsparser: 0.9.1 + unicode-match-property-ecmascript: 2.0.0 + unicode-match-property-value-ecmascript: 2.1.0 + dev: true + + /registry-auth-token@5.0.2: + resolution: {integrity: sha512-o/3ikDxtXaA59BmZuZrJZDJv8NMDGSj+6j6XaeBmHw8eY1i1qd9+6H+LjVvQXx3HN6aRCGa1cUdJ9RaJZUugnQ==} + engines: {node: '>=14'} + dependencies: + '@pnpm/npm-conf': 2.2.2 + dev: true + + /regjsparser@0.9.1: + resolution: {integrity: sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==} + hasBin: true + dependencies: + jsesc: 0.5.0 + dev: true + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /resolve-cwd@3.0.0: + resolution: {integrity: sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==} + engines: {node: '>=8'} + dependencies: + resolve-from: 5.0.0 + dev: true + + /resolve-from@4.0.0: + resolution: {integrity: sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==} + engines: {node: '>=4'} + dev: true + + /resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + dev: true + + /resolve-pkg-maps@1.0.0: + resolution: {integrity: sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==} + dev: true + + /resolve.exports@2.0.2: + resolution: {integrity: sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==} + engines: {node: '>=10'} + dev: true + + /resolve@1.22.8: + resolution: {integrity: sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==} + hasBin: true + dependencies: + is-core-module: 2.13.1 + path-parse: 1.0.7 + supports-preserve-symlinks-flag: 1.0.0 + dev: true + + /reusify@1.0.4: + resolution: {integrity: sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==} + engines: {iojs: '>=1.0.0', node: '>=0.10.0'} + dev: true + + /rimraf@3.0.2: + resolution: {integrity: sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==} + hasBin: true + dependencies: + glob: 7.2.3 + dev: true + + /run-parallel@1.2.0: + resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + dependencies: + queue-microtask: 1.2.3 + dev: true + + /safe-array-concat@1.1.0: + resolution: {integrity: sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: true + + /safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: true + + /safe-regex-test@1.0.2: + resolution: {integrity: sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-regex: 1.1.4 + dev: true + + /semantic-release@22.0.12(typescript@5.3.3): + resolution: {integrity: sha512-0mhiCR/4sZb00RVFJIUlMuiBkW3NMpVIW2Gse7noqEMoFGkvfPPAImEQbkBV8xga4KOPP4FdTRYuLLy32R1fPw==} + engines: {node: ^18.17 || >=20.6.1} + hasBin: true + dependencies: + '@semantic-release/commit-analyzer': 11.1.0(semantic-release@22.0.12) + '@semantic-release/error': 4.0.0 + '@semantic-release/github': 9.2.6(semantic-release@22.0.12) + '@semantic-release/npm': 11.0.2(semantic-release@22.0.12) + '@semantic-release/release-notes-generator': 12.1.0(semantic-release@22.0.12) + aggregate-error: 5.0.0 + cosmiconfig: 8.3.6(typescript@5.3.3) + debug: 4.3.4 + env-ci: 10.0.0 + execa: 8.0.1 + figures: 6.0.1 + find-versions: 5.1.0 + get-stream: 6.0.1 + git-log-parser: 1.2.0 + hook-std: 3.0.0 + hosted-git-info: 7.0.1 + import-from-esm: 1.3.3 + lodash-es: 4.17.21 + marked: 9.1.6 + marked-terminal: 6.2.0(marked@9.1.6) + micromatch: 4.0.5 + p-each-series: 3.0.0 + p-reduce: 3.0.0 + read-pkg-up: 11.0.0 + resolve-from: 5.0.0 + semver: 7.5.4 + semver-diff: 4.0.0 + signale: 1.4.0 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + - typescript + dev: true + + /semver-diff@4.0.0: + resolution: {integrity: sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==} + engines: {node: '>=12'} + dependencies: + semver: 7.5.4 + dev: true + + /semver-regex@4.0.5: + resolution: {integrity: sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==} + engines: {node: '>=12'} + dev: true + + /semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + dev: true + + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + dev: true + + /set-function-length@1.2.0: + resolution: {integrity: sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + dev: true + + /set-function-name@2.0.1: + resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.1 + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + object-inspect: 1.13.1 + dev: true + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: true + + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: true + + /signale@1.4.0: + resolution: {integrity: sha512-iuh+gPf28RkltuJC7W5MRi6XAjTDCAPC/prJUpQoG4vIP3MJZ+GTydVnodXA7pwvTKb2cA0m9OFZW/cdWy/I/w==} + engines: {node: '>=6'} + dependencies: + chalk: 2.4.2 + figures: 2.0.0 + pkg-conf: 2.1.0 + dev: true + + /sisteransi@1.0.5: + resolution: {integrity: sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==} + dev: true + + /skin-tone@2.0.0: + resolution: {integrity: sha512-kUMbT1oBJCpgrnKoSr0o6wPtvRWT9W9UKvGLwfJYO2WuahZRHOpEyL1ckyMGgMWh0UdpmaoFqKKD29WTomNEGA==} + engines: {node: '>=8'} + dependencies: + unicode-emoji-modifier-base: 1.0.0 + dev: true + + /slash@3.0.0: + resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} + engines: {node: '>=8'} + dev: true + + /slash@5.1.0: + resolution: {integrity: sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==} + engines: {node: '>=14.16'} + dev: true + + /source-map-support@0.5.13: + resolution: {integrity: sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: true + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: true + + /spawn-error-forwarder@1.0.0: + resolution: {integrity: sha512-gRjMgK5uFjbCvdibeGJuy3I5OYz6VLoVdsOJdA6wV0WlfQVLFueoqMxwwYD9RODdgb6oUIvlRlsyFSiQkMKu0g==} + dev: true + + /spdx-correct@3.2.0: + resolution: {integrity: sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==} + dependencies: + spdx-expression-parse: 3.0.1 + spdx-license-ids: 3.0.16 + dev: true + + /spdx-exceptions@2.3.0: + resolution: {integrity: sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==} + dev: true + + /spdx-expression-parse@3.0.1: + resolution: {integrity: sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==} + dependencies: + spdx-exceptions: 2.3.0 + spdx-license-ids: 3.0.16 + dev: true + + /spdx-license-ids@3.0.16: + resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} + dev: true + + /split2@1.0.0: + resolution: {integrity: sha512-NKywug4u4pX/AZBB1FCPzZ6/7O+Xhz1qMVbzTvvKvikjO99oPN87SkK08mEY9P63/5lWjK+wgOOgApnTg5r6qg==} + dependencies: + through2: 2.0.5 + dev: true + + /split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + dev: true + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: true + + /stack-utils@2.0.6: + resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==} + engines: {node: '>=10'} + dependencies: + escape-string-regexp: 2.0.0 + dev: true + + /stream-combiner2@1.1.1: + resolution: {integrity: sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==} + dependencies: + duplexer2: 0.1.4 + readable-stream: 2.3.8 + dev: true + + /string-length@4.0.2: + resolution: {integrity: sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==} + engines: {node: '>=10'} + dependencies: + char-regex: 1.0.2 + strip-ansi: 6.0.1 + dev: true + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: true + + /string.prototype.trim@1.2.8: + resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string.prototype.trimend@1.0.7: + resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string.prototype.trimstart@1.0.7: + resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: true + + /string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + dependencies: + safe-buffer: 5.1.2 + dev: true + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-bom@3.0.0: + resolution: {integrity: sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==} + engines: {node: '>=4'} + dev: true + + /strip-bom@4.0.0: + resolution: {integrity: sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==} + engines: {node: '>=8'} + dev: true + + /strip-final-newline@2.0.0: + resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} + engines: {node: '>=6'} + dev: true + + /strip-final-newline@3.0.0: + resolution: {integrity: sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==} + engines: {node: '>=12'} + dev: true + + /strip-json-comments@2.0.1: + resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} + engines: {node: '>=0.10.0'} + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: true + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-hyperlinks@3.0.0: + resolution: {integrity: sha512-QBDPHyPQDRTy9ku4URNGY5Lah8PAaXs6tAAwp55sL5WCsSW7GIfdf6W5ixfziW+t7wh3GVvHyHHyQ1ESsoRvaA==} + engines: {node: '>=14.18'} + dependencies: + has-flag: 4.0.0 + supports-color: 7.2.0 + dev: true + + /supports-preserve-symlinks-flag@1.0.0: + resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} + engines: {node: '>= 0.4'} + dev: true + + /synckit@0.8.8: + resolution: {integrity: sha512-HwOKAP7Wc5aRGYdKH+dw0PRRpbO841v2DENBtjnR5HFWoiNByAl7vrx3p0G/rCyYXQsrxqtX48TImFtPcIHSpQ==} + engines: {node: ^14.18.0 || >=16.0.0} + dependencies: + '@pkgr/core': 0.1.1 + tslib: 2.6.2 + dev: true + + /temp-dir@3.0.0: + resolution: {integrity: sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==} + engines: {node: '>=14.16'} + dev: true + + /tempy@3.1.0: + resolution: {integrity: sha512-7jDLIdD2Zp0bDe5r3D2qtkd1QOCacylBuL7oa4udvN6v2pqr4+LcCr67C8DR1zkpaZ8XosF5m1yQSabKAW6f2g==} + engines: {node: '>=14.16'} + dependencies: + is-stream: 3.0.0 + temp-dir: 3.0.0 + type-fest: 2.19.0 + unique-string: 3.0.0 + dev: true + + /test-exclude@6.0.0: + resolution: {integrity: sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==} + engines: {node: '>=8'} + dependencies: + '@istanbuljs/schema': 0.1.3 + glob: 7.2.3 + minimatch: 3.1.2 + dev: true + + /text-extensions@2.4.0: + resolution: {integrity: sha512-te/NtwBwfiNRLf9Ijqx3T0nlqZiQ2XrrtBvu+cLL8ZRrGkO0NHTug8MYFKyoSrv/sHTaSKfilUkizV6XhxMJ3g==} + engines: {node: '>=8'} + dev: true + + /text-table@0.2.0: + resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} + dev: true + + /through2@2.0.5: + resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} + dependencies: + readable-stream: 2.3.8 + xtend: 4.0.2 + dev: true + + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: true + + /tmpl@1.0.5: + resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} + dev: true + + /to-fast-properties@2.0.0: + resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} + engines: {node: '>=4'} + dev: true + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /traverse@0.6.8: + resolution: {integrity: sha512-aXJDbk6SnumuaZSANd21XAo15ucCDE38H4fkqiGsc3MhCK+wOlZvLP9cB/TvpHT0mOyWgC4Z8EwRlzqYSUzdsA==} + engines: {node: '>= 0.4'} + dev: true + + /ts-api-utils@1.0.3(typescript@5.3.3): + resolution: {integrity: sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg==} + engines: {node: '>=16.13.0'} + peerDependencies: + typescript: '>=4.2.0' + dependencies: + typescript: 5.3.3 + dev: true + + /ts-node@10.9.2(@types/node@20.11.5)(typescript@5.3.3): + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.11.5 + acorn: 8.11.3 + acorn-walk: 8.3.2 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.3.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + dev: true + + /tsconfig-paths@3.15.0: + resolution: {integrity: sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==} + dependencies: + '@types/json5': 0.0.29 + json5: 1.0.2 + minimist: 1.2.8 + strip-bom: 3.0.0 + dev: true + + /tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + dev: true + + /type-check@0.4.0: + resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} + engines: {node: '>= 0.8.0'} + dependencies: + prelude-ls: 1.2.1 + dev: true + + /type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + + /type-fest@0.20.2: + resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} + engines: {node: '>=10'} + dev: true + + /type-fest@0.21.3: + resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} + engines: {node: '>=10'} + dev: true + + /type-fest@1.4.0: + resolution: {integrity: sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==} + engines: {node: '>=10'} + dev: true + + /type-fest@2.19.0: + resolution: {integrity: sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==} + engines: {node: '>=12.20'} + dev: true + + /type-fest@3.13.1: + resolution: {integrity: sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==} + engines: {node: '>=14.16'} + dev: true + + /type-fest@4.10.0: + resolution: {integrity: sha512-NPaKJsb4wyJ16qc8zBQrWswLKv/YirgBFykvUQ1Iajt2wd+twC8E4hFXdlIXqiMl6kWA0zY8tUJ9ELVAdu5h7w==} + engines: {node: '>=16'} + dev: true + + /typed-array-buffer@1.0.0: + resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-length@1.0.0: + resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-byte-offset@1.0.0: + resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: true + + /typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.5 + for-each: 0.3.3 + is-typed-array: 1.1.12 + dev: true + + /typescript@5.3.3: + resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + + /uglify-js@3.17.4: + resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + engines: {node: '>=0.8.0'} + hasBin: true + requiresBuild: true + dev: true + optional: true + + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.5 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: true + + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + dev: true + + /unicode-canonical-property-names-ecmascript@2.0.0: + resolution: {integrity: sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==} + engines: {node: '>=4'} + dev: true + + /unicode-emoji-modifier-base@1.0.0: + resolution: {integrity: sha512-yLSH4py7oFH3oG/9K+XWrz1pSi3dfUrWEnInbxMfArOfc1+33BlGPQtLsOYwvdMy11AwUBetYuaRxSPqgkq+8g==} + engines: {node: '>=4'} + dev: true + + /unicode-match-property-ecmascript@2.0.0: + resolution: {integrity: sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==} + engines: {node: '>=4'} + dependencies: + unicode-canonical-property-names-ecmascript: 2.0.0 + unicode-property-aliases-ecmascript: 2.1.0 + dev: true + + /unicode-match-property-value-ecmascript@2.1.0: + resolution: {integrity: sha512-qxkjQt6qjg/mYscYMC0XKRn3Rh0wFPlfxB0xkt9CfyTvpX1Ra0+rAmdX2QyAobptSEvuy4RtpPRui6XkV+8wjA==} + engines: {node: '>=4'} + dev: true + + /unicode-property-aliases-ecmascript@2.1.0: + resolution: {integrity: sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==} + engines: {node: '>=4'} + dev: true + + /unicorn-magic@0.1.0: + resolution: {integrity: sha512-lRfVq8fE8gz6QMBuDM6a+LO3IAzTi05H6gCVaUpir2E1Rwpo4ZUog45KpNXKC/Mn3Yb9UDuHumeFTo9iV/D9FQ==} + engines: {node: '>=18'} + dev: true + + /unique-string@3.0.0: + resolution: {integrity: sha512-VGXBUVwxKMBUznyffQweQABPRRW1vHZAbadFZud4pLFAqRGvv/96vafgjWFqzourzr8YonlQiPgH0YCJfawoGQ==} + engines: {node: '>=12'} + dependencies: + crypto-random-string: 4.0.0 + dev: true + + /universal-user-agent@6.0.1: + resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} + dev: true + + /universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + dev: true + + /update-browserslist-db@1.0.13(browserslist@4.22.2): + resolution: {integrity: sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==} + hasBin: true + peerDependencies: + browserslist: '>= 4.21.0' + dependencies: + browserslist: 4.22.2 + escalade: 3.1.1 + picocolors: 1.0.0 + dev: true + + /uri-js@4.4.1: + resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} + dependencies: + punycode: 2.3.1 + dev: true + + /url-join@5.0.0: + resolution: {integrity: sha512-n2huDr9h9yzd6exQVnH/jU5mr+Pfx08LRXXZhkLLetAMESRj+anQsTAh940iMrIetKAmry9coFuZQ2jY8/p3WA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + dev: true + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: true + + /v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + dev: true + + /v8-to-istanbul@9.2.0: + resolution: {integrity: sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA==} + engines: {node: '>=10.12.0'} + dependencies: + '@jridgewell/trace-mapping': 0.3.22 + '@types/istanbul-lib-coverage': 2.0.6 + convert-source-map: 2.0.0 + dev: true + + /validate-npm-package-license@3.0.4: + resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} + dependencies: + spdx-correct: 3.2.0 + spdx-expression-parse: 3.0.1 + dev: true + + /walker@1.0.8: + resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} + dependencies: + makeerror: 1.0.12 + dev: true + + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: true + + /which-typed-array@1.1.13: + resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + dev: true + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: true + + /write-file-atomic@4.0.2: + resolution: {integrity: sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==} + engines: {node: ^12.13.0 || ^14.15.0 || >=16.0.0} + dependencies: + imurmurhash: 0.1.4 + signal-exit: 3.0.7 + dev: true + + /xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + dev: true + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: true + + /yallist@3.1.1: + resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} + dev: true + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + dev: true + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: true + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: true + + /yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + dev: true + + /yocto-queue@0.1.0: + resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} + engines: {node: '>=10'} + dev: true diff --git a/specs/commercelayer.spec.ts b/specs/commercelayer.spec.ts new file mode 100644 index 0000000..8556170 --- /dev/null +++ b/specs/commercelayer.spec.ts @@ -0,0 +1,56 @@ + +import { CommerceLayerProvisioningClient, CommerceLayerProvisioningStatic } from '../src' +import { getClient } from '../test/common' +import { RawResponseReader } from '../src/interceptor' + + +let clp: CommerceLayerProvisioningClient + + +beforeAll(async () => { clp = await getClient() }) + + +describe('SDK:commercelayer suite', () => { + + it('commercelayer.resources', async () => { + + const resources = CommerceLayerProvisioningStatic.resources() + + expect(resources).not.toBeUndefined() + expect(Array.isArray(resources)).toBeTruthy() + expect(resources.length).toBeGreaterThan(0) + + const resourcesInstance = clp.resources() + expect(resourcesInstance).toStrictEqual(resources) + + }) + + + + it('commercelayer.rawResponse', async () => { + + jest.setTimeout(10000) + const headers = true + + const cli = await getClient(true) + + const reader = cli.addRawResponseReader({ headers }) + expect(reader).not.toBeUndefined() + expect(reader.id).toBeGreaterThanOrEqual(0) + + await cli.roles.list({ pageSize: 1 }) + expect(reader.rawResponse?.data).not.toBeUndefined() + if (headers) expect(reader.headers).not.toBeUndefined() + else expect(reader.headers).toBeUndefined() + + cli.removeRawResponseReader(reader.id as number) + cli.removeRawResponseReader(reader) + cli.removeRawResponseReader(0) + cli.removeRawResponseReader({ id: undefined } as RawResponseReader) + + clp = await getClient() + + }) + + +}) diff --git a/specs/error.spec.ts b/specs/error.spec.ts new file mode 100644 index 0000000..499b9f1 --- /dev/null +++ b/specs/error.spec.ts @@ -0,0 +1,44 @@ + +import { CommerceLayerProvisioningClient } from '../src' +import { Organizations } from '../src/api' +import { ErrorType } from '../src/error' +import { getClient } from '../test/common' + + +let clp: CommerceLayerProvisioningClient + + +beforeAll(async () => { clp = await getClient(true) }) + + +describe('SDK:error suite', () => { + + it('ApiError', async () => { + try { + await clp.roles.retrieve('fake-id') + } catch (error) { + expect(clp.isApiError(error)).toBeTruthy() + expect(error.status).toBe(404) + } + }) + + + it('ApiError.first', async () => { + try { + await clp.roles.create({ name: '', organization: { id: '', type: Organizations.TYPE} }) + } catch (error) { + expect(error.first()).not.toBeUndefined() + } + }) + + + it('ApiError.type', async () => { + try { + clp.config({ domain: 'fake.domain.xx', accessToken: 'fake-access-token' }) + await clp.roles.list({ pageSize: 1}) + } catch (error) { + expect(error.type).toEqual(ErrorType.RESPONSE) + } + }) + +}) diff --git a/specs/headers.spec.ts b/specs/headers.spec.ts new file mode 100644 index 0000000..7e2259f --- /dev/null +++ b/specs/headers.spec.ts @@ -0,0 +1,59 @@ + +import { CommerceLayerProvisioningClient } from '../src' +import { getClient, CommonData, handleError, interceptRequest } from '../test/common' + + + +let clp: CommerceLayerProvisioningClient + + +beforeAll(async () => { clp = await getClient(true) }) + + +describe('Test headers', () => { + + it('Request headers', async () => { + + const testHeaderValue = 'test-value' + const params = { fields: { } } + const options = { + ...CommonData.options, + headers: { + 'test-header': testHeaderValue, + 'Content-Type': 'application/json' + } + } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.headers).toBeDefined() + if (config.headers) { + expect(config.headers['test-header']).toBe(testHeaderValue) + expect(config.headers['Content-Type']).toBe('application/vnd.api+json') + } + return interceptRequest() + }) + + await clp.user.retrieve(params, options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + + + it('Response headers', async () => { + + const params = { fields: { } } + + const reader = clp.addRawResponseReader({ headers: true }) + + await clp.user.retrieve(params, CommonData.options) + + expect(reader.headers).not.toBeUndefined() + expect(reader.headers?.['x-ratelimit-limit']).not.toBeUndefined() + + clp.removeRawResponseReader(reader) + + }) + + +}) diff --git a/specs/jsonapi.spec.ts b/specs/jsonapi.spec.ts new file mode 100644 index 0000000..cadda8a --- /dev/null +++ b/specs/jsonapi.spec.ts @@ -0,0 +1,96 @@ + +import { CommerceLayerProvisioningClient } from '../src' +import { getClient, TestData } from '../test/common' +import { normalize, denormalize } from '../src/jsonapi' +import { ResourceTypeLock } from '../src/api' +import { isEqual } from 'lodash' + + +let clp: CommerceLayerProvisioningClient + + +beforeAll(async () => { clp = await getClient() }) + + +describe('SDK:jsonapi suite', () => { + + it('jsonapi.normalize', async () => { + + const type: ResourceTypeLock = 'memberships' + + const resource = { + id: TestData.id, + type, + reference: TestData.reference, + reference_origin: TestData.reference_origin, + metadata: TestData.metadata, + user_email: 'user@sdk-test.org', + organization: clp.organizations.relationship(TestData.id), + role: clp.roles.relationship(TestData.id) + } + + const expected = { + id: resource.id, + type, + attributes: { + reference: resource.reference, + reference_origin: resource.reference_origin, + metadata: resource.metadata, + user_email: resource.user_email + }, + relationships: { + organization: { + data: resource.organization + }, + role: { + data: resource.role + } + } + } + + const normalized = normalize(resource) + + expect(isEqual(normalized, expected)).toBeTruthy() + + }) + + + it('jsonapi.denormalize', async () => { + + const jsonApi = { + data: { + id: TestData.id + '00', + type: 'users', + attributes: { + user_email: 'user@sdk-test.org', + reference: TestData.reference, + reference_origin: TestData.reference_origin, + metadata: TestData.metadata + }, + relationships: { + organization: { data: { type: 'organizations', id: TestData.id } }, + role: { data: null } + } + }, + included: [{ id: TestData.id, type: 'organizations', attributes: { name: 'Org_Name' } }], + links: { self: 'link' }, + } + + const expected = { + id: TestData.id + '00', + type: 'users', + user_email: 'user@sdk-test.org', + reference: TestData.reference, + reference_origin: TestData.reference_origin, + metadata: TestData.metadata, + organization: { type: 'organizations', id: TestData.id, name: 'Org_Name' }, + role: null + } + + const denormalized = denormalize(jsonApi) + + expect(isEqual(expected, denormalized)).toBeTruthy() + + }) + +}) diff --git a/specs/resource.spec.ts b/specs/resource.spec.ts new file mode 100644 index 0000000..e090c29 --- /dev/null +++ b/specs/resource.spec.ts @@ -0,0 +1,98 @@ + +import { CommerceLayerProvisioningClient, Membership, Role } from '../src' +import { ListResponse } from '../src/resource' +import { getClient } from '../test/common' + + +let clp: CommerceLayerProvisioningClient +let memberships: ListResponse +let tempId: string + + +beforeAll(async () => { + clp = await getClient(true) + memberships = await clp.memberships.list({ pageSize: 1}) +}) + + +describe('SDK:resource suite', () => { + + it('resource.first', async () => { + const first = memberships.first() + expect(first?.id).not.toBeUndefined() + }) + + + it('resource.last', async () => { + const first = memberships.first() + const last = memberships.last() + expect(last?.id).not.toBeUndefined() + expect(first).toEqual(last) + }) + + + it('resource.get', async () => { + const role = memberships.get(0) + expect(role?.id).not.toBeUndefined() + }) + + + it('resource.retrieve', async () => { + const id = memberships.first()?.id as string + const user = await clp.memberships.retrieve(id) + expect(user.id).toEqual(id) + }) + + + it('resource.update', async () => { + const id = memberships.first()?.id as string + const reference = String(Date.now()) + const role = await clp.memberships.update({ id, reference }) + expect(role.reference).toEqual(reference) + }) + + + it('resource.singleton', async () => { + const user = await clp.user.retrieve() + expect(user.id).not.toBeNull() + expect(user.id).not.toBeUndefined() + }) + + + it('resource.create', async () => { + const user_email = 'spec@provisioning-sdk-test.org' + const org = (await clp.organizations.list()).first() + const role = (await clp.roles.list()).first() + if (!org || !role) throw new Error('Missing role or organization') + const ms = await clp.memberships.create({ + user_email, + organization: clp.organizations.relationship(org), + role: clp.roles.relationship(role) + }) + expect(ms.id).not.toBeUndefined() + expect(ms.user_email).toEqual(user_email) + tempId = ms.id + }) + + + it('resource.delete', async () => { + await clp.memberships.delete(tempId) + try { + await clp.memberships.retrieve(tempId) + } catch (error) { + expect(error.code).toEqual("404") + expect(error.status).toEqual(404) + } + }) + + + it('resource.fetch', async () => { + const org = (await clp.organizations.list({ pageSize: 1 })).first() + if (!org) return + const mships = await clp.organizations.memberships(org.id) + expect (mships.length).toBeGreaterThan(0) + const o = await clp.memberships.organization(mships.first()?.id || '') + expect (o.id).toBe(org.id) + }) + +}) diff --git a/specs/resources/api_credentials.spec.ts b/specs/resources/api_credentials.spec.ts new file mode 100644 index 0000000..99dcf36 --- /dev/null +++ b/specs/resources/api_credentials.spec.ts @@ -0,0 +1,243 @@ +/** + * ©2024 Commerce Layer Inc. + * Source code generated automatically by SDK codegen + **/ + +import { CommerceLayerProvisioningClient, ApiCredential } from '../../src' +import { isEqual } from 'lodash' +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { getClient, TestData, CommonData, handleError, interceptRequest, checkCommon, checkCommonData, checkCommonParamsList, checkCommonParams, currentAccessToken, randomValue } from '../../test/common' + + + +let clp: CommerceLayerProvisioningClient + + +beforeAll(async () => { clp = await getClient() }) + + +describe('ApiCredentials resource', () => { + + const resourceType = 'api_credentials' + + + /* spec.create.start */ + it(resourceType + '.create', async () => { + + const createAttributes = { + name: randomValue('string', 'name'), + kind: randomValue('string', 'kind'), + organization: clp.organizations.relationship(TestData.id), + role: clp.roles.relationship(TestData.id), + } + + const attributes = { ...createAttributes, reference: TestData.reference } + const params = { fields: { [resourceType]: CommonData.paramsFields } } + const resData = attributes + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('post') + checkCommon(config, resourceType) + checkCommonData(config, resourceType, attributes) + expect(clp[resourceType].isApiCredential(config.data.data)).toBeTruthy() + return interceptRequest() + }) + + await clp[resourceType].create(resData, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.create.stop */ + + + /* spec.retrieve.start */ + it(resourceType + '.retrieve', async () => { + + const id = TestData.id + const params = { fields: {[resourceType]: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken) + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].retrieve(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.retrieve.stop */ + + + /* spec.update.start */ + it(resourceType + '.update', async () => { + + const attributes = { reference_origin: TestData.reference_origin, metadata: TestData.metadata } + const params = { fields: { [resourceType]: CommonData.paramsFields } } + const resData = { id: TestData.id, ...attributes} + + const intId = clp.addRequestInterceptor((config) => { + if (config.method !== 'get') { + expect(config.method).toBe('patch') + checkCommon(config, resourceType, resData.id, currentAccessToken) + checkCommonData(config, resourceType, attributes, resData.id) + } + return interceptRequest() + }) + + await clp[resourceType].update(resData, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.update.stop */ + + + /* spec.delete.start */ + it(resourceType + '.delete', async () => { + + const id = TestData.id + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('delete') + checkCommon(config, resourceType, id, currentAccessToken) + return interceptRequest() + }) + + await clp[resourceType].delete(id, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.delete.stop */ + + + /* spec.list.start */ + it(resourceType + '.list', async () => { + + const params = CommonData.paramsList + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType) + checkCommonParamsList(config, params) + return interceptRequest() + }) + + await clp[resourceType].list(params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.list.stop */ + + + /* spec.type.start */ + it(resourceType + '.type', async () => { + + const resource = { id: TestData.id, type: resourceType } + expect(clp[resourceType].isApiCredential(resource)).toBeTruthy() + + const type = clp[resourceType].type() + expect(type).toBe(resourceType) + + }) + /* spec.type.stop */ + + + /* spec.relationship.start */ + it(resourceType + '.relationship', async () => { + + const relId = clp[resourceType].relationship(TestData.id) + expect(isEqual(relId, { id: TestData.id, type: resourceType})) + + const relResId = clp[resourceType].relationship({ id: TestData.id, type: resourceType }) + expect(isEqual(relResId, { id: TestData.id, type: resourceType})) + + }) + /* spec.relationship.stop */ + + + /* spec.parse.start */ + it(resourceType + '.parse', async () => { + + const reference = 'myReferenceId' + + const payload = ` + { + "data": { + "id": "AbcdEfgHiL", + "meta": { + "mode": "test", + "organization_id": "myOrgId" + }, + "type": "${resourceType}", + "links": { + "self": "/api/${resourceType}/AbcdEfgHiL" + }, + "attributes": { + "metadata": {}, + "reference": "${reference}", + "created_at": "2023-10-01T05:53:29.296Z", + "updated_at": "2023-10-10T08:52:13.251Z" + } + } + } + ` + + const res = clp[resourceType].parse(payload) as ApiCredential + + expect(res.type).toBe(resourceType) + expect(res.reference).toBe(reference) + + }) + /* spec.parse.stop */ + + + + /* relationship.organization start */ + it(resourceType + '.organization', async () => { + + const id = TestData.id + const params = { fields: { organizations: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'organization') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].organization(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.organization stop */ + + + /* relationship.role start */ + it(resourceType + '.role', async () => { + + const id = TestData.id + const params = { fields: { roles: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'role') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].role(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.role stop */ + + +}) diff --git a/specs/resources/application_memberships.spec.ts b/specs/resources/application_memberships.spec.ts new file mode 100644 index 0000000..d2741da --- /dev/null +++ b/specs/resources/application_memberships.spec.ts @@ -0,0 +1,285 @@ +/** + * ©2024 Commerce Layer Inc. + * Source code generated automatically by SDK codegen + **/ + +import { CommerceLayerProvisioningClient, ApplicationMembership } from '../../src' +import { isEqual } from 'lodash' +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { getClient, TestData, CommonData, handleError, interceptRequest, checkCommon, checkCommonData, checkCommonParamsList, checkCommonParams, currentAccessToken, randomValue } from '../../test/common' + + + +let clp: CommerceLayerProvisioningClient + + +beforeAll(async () => { clp = await getClient() }) + + +describe('ApplicationMemberships resource', () => { + + const resourceType = 'application_memberships' + + + /* spec.create.start */ + it(resourceType + '.create', async () => { + + const createAttributes = { + api_credential: clp.api_credentials.relationship(TestData.id), + membership: clp.memberships.relationship(TestData.id), + organization: clp.organizations.relationship(TestData.id), + role: clp.roles.relationship(TestData.id), + } + + const attributes = { ...createAttributes, reference: TestData.reference } + const params = { fields: { [resourceType]: CommonData.paramsFields } } + const resData = attributes + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('post') + checkCommon(config, resourceType) + checkCommonData(config, resourceType, attributes) + expect(clp[resourceType].isApplicationMembership(config.data.data)).toBeTruthy() + return interceptRequest() + }) + + await clp[resourceType].create(resData, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.create.stop */ + + + /* spec.retrieve.start */ + it(resourceType + '.retrieve', async () => { + + const id = TestData.id + const params = { fields: {[resourceType]: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken) + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].retrieve(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.retrieve.stop */ + + + /* spec.update.start */ + it(resourceType + '.update', async () => { + + const attributes = { reference_origin: TestData.reference_origin, metadata: TestData.metadata } + const params = { fields: { [resourceType]: CommonData.paramsFields } } + const resData = { id: TestData.id, ...attributes} + + const intId = clp.addRequestInterceptor((config) => { + if (config.method !== 'get') { + expect(config.method).toBe('patch') + checkCommon(config, resourceType, resData.id, currentAccessToken) + checkCommonData(config, resourceType, attributes, resData.id) + } + return interceptRequest() + }) + + await clp[resourceType].update(resData, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.update.stop */ + + + /* spec.delete.start */ + it(resourceType + '.delete', async () => { + + const id = TestData.id + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('delete') + checkCommon(config, resourceType, id, currentAccessToken) + return interceptRequest() + }) + + await clp[resourceType].delete(id, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.delete.stop */ + + + /* spec.list.start */ + it(resourceType + '.list', async () => { + + const params = CommonData.paramsList + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType) + checkCommonParamsList(config, params) + return interceptRequest() + }) + + await clp[resourceType].list(params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.list.stop */ + + + /* spec.type.start */ + it(resourceType + '.type', async () => { + + const resource = { id: TestData.id, type: resourceType } + expect(clp[resourceType].isApplicationMembership(resource)).toBeTruthy() + + const type = clp[resourceType].type() + expect(type).toBe(resourceType) + + }) + /* spec.type.stop */ + + + /* spec.relationship.start */ + it(resourceType + '.relationship', async () => { + + const relId = clp[resourceType].relationship(TestData.id) + expect(isEqual(relId, { id: TestData.id, type: resourceType})) + + const relResId = clp[resourceType].relationship({ id: TestData.id, type: resourceType }) + expect(isEqual(relResId, { id: TestData.id, type: resourceType})) + + }) + /* spec.relationship.stop */ + + + /* spec.parse.start */ + it(resourceType + '.parse', async () => { + + const reference = 'myReferenceId' + + const payload = ` + { + "data": { + "id": "AbcdEfgHiL", + "meta": { + "mode": "test", + "organization_id": "myOrgId" + }, + "type": "${resourceType}", + "links": { + "self": "/api/${resourceType}/AbcdEfgHiL" + }, + "attributes": { + "metadata": {}, + "reference": "${reference}", + "created_at": "2023-10-01T05:53:29.296Z", + "updated_at": "2023-10-10T08:52:13.251Z" + } + } + } + ` + + const res = clp[resourceType].parse(payload) as ApplicationMembership + + expect(res.type).toBe(resourceType) + expect(res.reference).toBe(reference) + + }) + /* spec.parse.stop */ + + + + /* relationship.api_credential start */ + it(resourceType + '.api_credential', async () => { + + const id = TestData.id + const params = { fields: { api_credentials: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'api_credential') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].api_credential(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.api_credential stop */ + + + /* relationship.membership start */ + it(resourceType + '.membership', async () => { + + const id = TestData.id + const params = { fields: { memberships: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'membership') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].membership(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.membership stop */ + + + /* relationship.organization start */ + it(resourceType + '.organization', async () => { + + const id = TestData.id + const params = { fields: { organizations: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'organization') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].organization(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.organization stop */ + + + /* relationship.role start */ + it(resourceType + '.role', async () => { + + const id = TestData.id + const params = { fields: { roles: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'role') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].role(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.role stop */ + + +}) diff --git a/specs/resources/memberships.spec.ts b/specs/resources/memberships.spec.ts new file mode 100644 index 0000000..eec6a0f --- /dev/null +++ b/specs/resources/memberships.spec.ts @@ -0,0 +1,285 @@ +/** + * ©2024 Commerce Layer Inc. + * Source code generated automatically by SDK codegen + **/ + +import { CommerceLayerProvisioningClient, Membership } from '../../src' +import { isEqual } from 'lodash' +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { getClient, TestData, CommonData, handleError, interceptRequest, checkCommon, checkCommonData, checkCommonParamsList, checkCommonParams, currentAccessToken, randomValue } from '../../test/common' + + + +let clp: CommerceLayerProvisioningClient + + +beforeAll(async () => { clp = await getClient() }) + + +describe('Memberships resource', () => { + + const resourceType = 'memberships' + + + /* spec.create.start */ + it(resourceType + '.create', async () => { + + const createAttributes = { + user_email: randomValue('string', 'user_email'), + organization: clp.organizations.relationship(TestData.id), + role: clp.roles.relationship(TestData.id), + application_memberships: [ clp.application_memberships.relationship(TestData.id) ], + } + + const attributes = { ...createAttributes, reference: TestData.reference } + const params = { fields: { [resourceType]: CommonData.paramsFields } } + const resData = attributes + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('post') + checkCommon(config, resourceType) + checkCommonData(config, resourceType, attributes) + expect(clp[resourceType].isMembership(config.data.data)).toBeTruthy() + return interceptRequest() + }) + + await clp[resourceType].create(resData, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.create.stop */ + + + /* spec.retrieve.start */ + it(resourceType + '.retrieve', async () => { + + const id = TestData.id + const params = { fields: {[resourceType]: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken) + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].retrieve(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.retrieve.stop */ + + + /* spec.update.start */ + it(resourceType + '.update', async () => { + + const attributes = { reference_origin: TestData.reference_origin, metadata: TestData.metadata } + const params = { fields: { [resourceType]: CommonData.paramsFields } } + const resData = { id: TestData.id, ...attributes} + + const intId = clp.addRequestInterceptor((config) => { + if (config.method !== 'get') { + expect(config.method).toBe('patch') + checkCommon(config, resourceType, resData.id, currentAccessToken) + checkCommonData(config, resourceType, attributes, resData.id) + } + return interceptRequest() + }) + + await clp[resourceType].update(resData, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.update.stop */ + + + /* spec.delete.start */ + it(resourceType + '.delete', async () => { + + const id = TestData.id + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('delete') + checkCommon(config, resourceType, id, currentAccessToken) + return interceptRequest() + }) + + await clp[resourceType].delete(id, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.delete.stop */ + + + /* spec.list.start */ + it(resourceType + '.list', async () => { + + const params = CommonData.paramsList + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType) + checkCommonParamsList(config, params) + return interceptRequest() + }) + + await clp[resourceType].list(params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.list.stop */ + + + /* spec.type.start */ + it(resourceType + '.type', async () => { + + const resource = { id: TestData.id, type: resourceType } + expect(clp[resourceType].isMembership(resource)).toBeTruthy() + + const type = clp[resourceType].type() + expect(type).toBe(resourceType) + + }) + /* spec.type.stop */ + + + /* spec.relationship.start */ + it(resourceType + '.relationship', async () => { + + const relId = clp[resourceType].relationship(TestData.id) + expect(isEqual(relId, { id: TestData.id, type: resourceType})) + + const relResId = clp[resourceType].relationship({ id: TestData.id, type: resourceType }) + expect(isEqual(relResId, { id: TestData.id, type: resourceType})) + + }) + /* spec.relationship.stop */ + + + /* spec.parse.start */ + it(resourceType + '.parse', async () => { + + const reference = 'myReferenceId' + + const payload = ` + { + "data": { + "id": "AbcdEfgHiL", + "meta": { + "mode": "test", + "organization_id": "myOrgId" + }, + "type": "${resourceType}", + "links": { + "self": "/api/${resourceType}/AbcdEfgHiL" + }, + "attributes": { + "metadata": {}, + "reference": "${reference}", + "created_at": "2023-10-01T05:53:29.296Z", + "updated_at": "2023-10-10T08:52:13.251Z" + } + } + } + ` + + const res = clp[resourceType].parse(payload) as Membership + + expect(res.type).toBe(resourceType) + expect(res.reference).toBe(reference) + + }) + /* spec.parse.stop */ + + + + /* relationship.organization start */ + it(resourceType + '.organization', async () => { + + const id = TestData.id + const params = { fields: { organizations: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'organization') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].organization(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.organization stop */ + + + /* relationship.role start */ + it(resourceType + '.role', async () => { + + const id = TestData.id + const params = { fields: { roles: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'role') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].role(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.role stop */ + + + /* relationship.application_memberships start */ + it(resourceType + '.application_memberships', async () => { + + const id = TestData.id + const params = { fields: { application_memberships: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'application_memberships') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].application_memberships(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.application_memberships stop */ + + + /* relationship.versions start */ + it(resourceType + '.versions', async () => { + + const id = TestData.id + const params = { fields: { versions: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'versions') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].versions(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.versions stop */ + + +}) diff --git a/specs/resources/organizations.spec.ts b/specs/resources/organizations.spec.ts new file mode 100644 index 0000000..84284b9 --- /dev/null +++ b/specs/resources/organizations.spec.ts @@ -0,0 +1,263 @@ +/** + * ©2024 Commerce Layer Inc. + * Source code generated automatically by SDK codegen + **/ + +import { CommerceLayerProvisioningClient, Organization } from '../../src' +import { isEqual } from 'lodash' +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { getClient, TestData, CommonData, handleError, interceptRequest, checkCommon, checkCommonData, checkCommonParamsList, checkCommonParams, currentAccessToken, randomValue } from '../../test/common' + + + +let clp: CommerceLayerProvisioningClient + + +beforeAll(async () => { clp = await getClient() }) + + +describe('Organizations resource', () => { + + const resourceType = 'organizations' + + + /* spec.create.start */ + it(resourceType + '.create', async () => { + + const createAttributes = { + name: randomValue('string', 'name'), + } + + const attributes = { ...createAttributes, reference: TestData.reference } + const params = { fields: { [resourceType]: CommonData.paramsFields } } + const resData = attributes + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('post') + checkCommon(config, resourceType) + checkCommonData(config, resourceType, attributes) + expect(clp[resourceType].isOrganization(config.data.data)).toBeTruthy() + return interceptRequest() + }) + + await clp[resourceType].create(resData, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.create.stop */ + + + /* spec.retrieve.start */ + it(resourceType + '.retrieve', async () => { + + const id = TestData.id + const params = { fields: {[resourceType]: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken) + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].retrieve(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.retrieve.stop */ + + + /* spec.update.start */ + it(resourceType + '.update', async () => { + + const attributes = { reference_origin: TestData.reference_origin, metadata: TestData.metadata } + const params = { fields: { [resourceType]: CommonData.paramsFields } } + const resData = { id: TestData.id, ...attributes} + + const intId = clp.addRequestInterceptor((config) => { + if (config.method !== 'get') { + expect(config.method).toBe('patch') + checkCommon(config, resourceType, resData.id, currentAccessToken) + checkCommonData(config, resourceType, attributes, resData.id) + } + return interceptRequest() + }) + + await clp[resourceType].update(resData, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.update.stop */ + + + /* spec.list.start */ + it(resourceType + '.list', async () => { + + const params = CommonData.paramsList + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType) + checkCommonParamsList(config, params) + return interceptRequest() + }) + + await clp[resourceType].list(params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.list.stop */ + + + /* spec.type.start */ + it(resourceType + '.type', async () => { + + const resource = { id: TestData.id, type: resourceType } + expect(clp[resourceType].isOrganization(resource)).toBeTruthy() + + const type = clp[resourceType].type() + expect(type).toBe(resourceType) + + }) + /* spec.type.stop */ + + + /* spec.relationship.start */ + it(resourceType + '.relationship', async () => { + + const relId = clp[resourceType].relationship(TestData.id) + expect(isEqual(relId, { id: TestData.id, type: resourceType})) + + const relResId = clp[resourceType].relationship({ id: TestData.id, type: resourceType }) + expect(isEqual(relResId, { id: TestData.id, type: resourceType})) + + }) + /* spec.relationship.stop */ + + + /* spec.parse.start */ + it(resourceType + '.parse', async () => { + + const reference = 'myReferenceId' + + const payload = ` + { + "data": { + "id": "AbcdEfgHiL", + "meta": { + "mode": "test", + "organization_id": "myOrgId" + }, + "type": "${resourceType}", + "links": { + "self": "/api/${resourceType}/AbcdEfgHiL" + }, + "attributes": { + "metadata": {}, + "reference": "${reference}", + "created_at": "2023-10-01T05:53:29.296Z", + "updated_at": "2023-10-10T08:52:13.251Z" + } + } + } + ` + + const res = clp[resourceType].parse(payload) as Organization + + expect(res.type).toBe(resourceType) + expect(res.reference).toBe(reference) + + }) + /* spec.parse.stop */ + + + + /* relationship.memberships start */ + it(resourceType + '.memberships', async () => { + + const id = TestData.id + const params = { fields: { memberships: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'memberships') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].memberships(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.memberships stop */ + + + /* relationship.roles start */ + it(resourceType + '.roles', async () => { + + const id = TestData.id + const params = { fields: { roles: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'roles') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].roles(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.roles stop */ + + + /* relationship.permissions start */ + it(resourceType + '.permissions', async () => { + + const id = TestData.id + const params = { fields: { permissions: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'permissions') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].permissions(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.permissions stop */ + + + /* relationship.api_credentials start */ + it(resourceType + '.api_credentials', async () => { + + const id = TestData.id + const params = { fields: { api_credentials: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'api_credentials') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].api_credentials(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.api_credentials stop */ + + +}) diff --git a/specs/resources/permissions.spec.ts b/specs/resources/permissions.spec.ts new file mode 100644 index 0000000..0751074 --- /dev/null +++ b/specs/resources/permissions.spec.ts @@ -0,0 +1,247 @@ +/** + * ©2024 Commerce Layer Inc. + * Source code generated automatically by SDK codegen + **/ + +import { CommerceLayerProvisioningClient, Permission } from '../../src' +import { isEqual } from 'lodash' +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { getClient, TestData, CommonData, handleError, interceptRequest, checkCommon, checkCommonData, checkCommonParamsList, checkCommonParams, currentAccessToken, randomValue } from '../../test/common' + + + +let clp: CommerceLayerProvisioningClient + + +beforeAll(async () => { clp = await getClient() }) + + +describe('Permissions resource', () => { + + const resourceType = 'permissions' + + + /* spec.create.start */ + it(resourceType + '.create', async () => { + + const createAttributes = { + can_create: randomValue('boolean', 'can_create'), + can_read: randomValue('boolean', 'can_read'), + can_update: randomValue('boolean', 'can_update'), + can_destroy: randomValue('boolean', 'can_destroy'), + subject: randomValue('string', 'subject'), + role: clp.roles.relationship(TestData.id), + } + + const attributes = { ...createAttributes, reference: TestData.reference } + const params = { fields: { [resourceType]: CommonData.paramsFields } } + const resData = attributes + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('post') + checkCommon(config, resourceType) + checkCommonData(config, resourceType, attributes) + expect(clp[resourceType].isPermission(config.data.data)).toBeTruthy() + return interceptRequest() + }) + + await clp[resourceType].create(resData, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.create.stop */ + + + /* spec.retrieve.start */ + it(resourceType + '.retrieve', async () => { + + const id = TestData.id + const params = { fields: {[resourceType]: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken) + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].retrieve(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.retrieve.stop */ + + + /* spec.update.start */ + it(resourceType + '.update', async () => { + + const attributes = { reference_origin: TestData.reference_origin, metadata: TestData.metadata } + const params = { fields: { [resourceType]: CommonData.paramsFields } } + const resData = { id: TestData.id, ...attributes} + + const intId = clp.addRequestInterceptor((config) => { + if (config.method !== 'get') { + expect(config.method).toBe('patch') + checkCommon(config, resourceType, resData.id, currentAccessToken) + checkCommonData(config, resourceType, attributes, resData.id) + } + return interceptRequest() + }) + + await clp[resourceType].update(resData, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.update.stop */ + + + /* spec.list.start */ + it(resourceType + '.list', async () => { + + const params = CommonData.paramsList + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType) + checkCommonParamsList(config, params) + return interceptRequest() + }) + + await clp[resourceType].list(params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.list.stop */ + + + /* spec.type.start */ + it(resourceType + '.type', async () => { + + const resource = { id: TestData.id, type: resourceType } + expect(clp[resourceType].isPermission(resource)).toBeTruthy() + + const type = clp[resourceType].type() + expect(type).toBe(resourceType) + + }) + /* spec.type.stop */ + + + /* spec.relationship.start */ + it(resourceType + '.relationship', async () => { + + const relId = clp[resourceType].relationship(TestData.id) + expect(isEqual(relId, { id: TestData.id, type: resourceType})) + + const relResId = clp[resourceType].relationship({ id: TestData.id, type: resourceType }) + expect(isEqual(relResId, { id: TestData.id, type: resourceType})) + + }) + /* spec.relationship.stop */ + + + /* spec.parse.start */ + it(resourceType + '.parse', async () => { + + const reference = 'myReferenceId' + + const payload = ` + { + "data": { + "id": "AbcdEfgHiL", + "meta": { + "mode": "test", + "organization_id": "myOrgId" + }, + "type": "${resourceType}", + "links": { + "self": "/api/${resourceType}/AbcdEfgHiL" + }, + "attributes": { + "metadata": {}, + "reference": "${reference}", + "created_at": "2023-10-01T05:53:29.296Z", + "updated_at": "2023-10-10T08:52:13.251Z" + } + } + } + ` + + const res = clp[resourceType].parse(payload) as Permission + + expect(res.type).toBe(resourceType) + expect(res.reference).toBe(reference) + + }) + /* spec.parse.stop */ + + + + /* relationship.organization start */ + it(resourceType + '.organization', async () => { + + const id = TestData.id + const params = { fields: { organizations: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'organization') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].organization(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.organization stop */ + + + /* relationship.role start */ + it(resourceType + '.role', async () => { + + const id = TestData.id + const params = { fields: { roles: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'role') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].role(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.role stop */ + + + /* relationship.versions start */ + it(resourceType + '.versions', async () => { + + const id = TestData.id + const params = { fields: { versions: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'versions') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].versions(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.versions stop */ + + +}) diff --git a/specs/resources/roles.spec.ts b/specs/resources/roles.spec.ts new file mode 100644 index 0000000..486decf --- /dev/null +++ b/specs/resources/roles.spec.ts @@ -0,0 +1,285 @@ +/** + * ©2024 Commerce Layer Inc. + * Source code generated automatically by SDK codegen + **/ + +import { CommerceLayerProvisioningClient, Role } from '../../src' +import { isEqual } from 'lodash' +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { getClient, TestData, CommonData, handleError, interceptRequest, checkCommon, checkCommonData, checkCommonParamsList, checkCommonParams, currentAccessToken, randomValue } from '../../test/common' + + + +let clp: CommerceLayerProvisioningClient + + +beforeAll(async () => { clp = await getClient() }) + + +describe('Roles resource', () => { + + const resourceType = 'roles' + + + /* spec.create.start */ + it(resourceType + '.create', async () => { + + const createAttributes = { + name: randomValue('string', 'name'), + organization: clp.organizations.relationship(TestData.id), + } + + const attributes = { ...createAttributes, reference: TestData.reference } + const params = { fields: { [resourceType]: CommonData.paramsFields } } + const resData = attributes + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('post') + checkCommon(config, resourceType) + checkCommonData(config, resourceType, attributes) + expect(clp[resourceType].isRole(config.data.data)).toBeTruthy() + return interceptRequest() + }) + + await clp[resourceType].create(resData, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.create.stop */ + + + /* spec.retrieve.start */ + it(resourceType + '.retrieve', async () => { + + const id = TestData.id + const params = { fields: {[resourceType]: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken) + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].retrieve(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.retrieve.stop */ + + + /* spec.update.start */ + it(resourceType + '.update', async () => { + + const attributes = { reference_origin: TestData.reference_origin, metadata: TestData.metadata } + const params = { fields: { [resourceType]: CommonData.paramsFields } } + const resData = { id: TestData.id, ...attributes} + + const intId = clp.addRequestInterceptor((config) => { + if (config.method !== 'get') { + expect(config.method).toBe('patch') + checkCommon(config, resourceType, resData.id, currentAccessToken) + checkCommonData(config, resourceType, attributes, resData.id) + } + return interceptRequest() + }) + + await clp[resourceType].update(resData, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.update.stop */ + + + /* spec.list.start */ + it(resourceType + '.list', async () => { + + const params = CommonData.paramsList + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType) + checkCommonParamsList(config, params) + return interceptRequest() + }) + + await clp[resourceType].list(params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.list.stop */ + + + /* spec.type.start */ + it(resourceType + '.type', async () => { + + const resource = { id: TestData.id, type: resourceType } + expect(clp[resourceType].isRole(resource)).toBeTruthy() + + const type = clp[resourceType].type() + expect(type).toBe(resourceType) + + }) + /* spec.type.stop */ + + + /* spec.relationship.start */ + it(resourceType + '.relationship', async () => { + + const relId = clp[resourceType].relationship(TestData.id) + expect(isEqual(relId, { id: TestData.id, type: resourceType})) + + const relResId = clp[resourceType].relationship({ id: TestData.id, type: resourceType }) + expect(isEqual(relResId, { id: TestData.id, type: resourceType})) + + }) + /* spec.relationship.stop */ + + + /* spec.parse.start */ + it(resourceType + '.parse', async () => { + + const reference = 'myReferenceId' + + const payload = ` + { + "data": { + "id": "AbcdEfgHiL", + "meta": { + "mode": "test", + "organization_id": "myOrgId" + }, + "type": "${resourceType}", + "links": { + "self": "/api/${resourceType}/AbcdEfgHiL" + }, + "attributes": { + "metadata": {}, + "reference": "${reference}", + "created_at": "2023-10-01T05:53:29.296Z", + "updated_at": "2023-10-10T08:52:13.251Z" + } + } + } + ` + + const res = clp[resourceType].parse(payload) as Role + + expect(res.type).toBe(resourceType) + expect(res.reference).toBe(reference) + + }) + /* spec.parse.stop */ + + + + /* relationship.organization start */ + it(resourceType + '.organization', async () => { + + const id = TestData.id + const params = { fields: { organizations: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'organization') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].organization(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.organization stop */ + + + /* relationship.permissions start */ + it(resourceType + '.permissions', async () => { + + const id = TestData.id + const params = { fields: { permissions: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'permissions') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].permissions(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.permissions stop */ + + + /* relationship.memberships start */ + it(resourceType + '.memberships', async () => { + + const id = TestData.id + const params = { fields: { memberships: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'memberships') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].memberships(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.memberships stop */ + + + /* relationship.api_credentials start */ + it(resourceType + '.api_credentials', async () => { + + const id = TestData.id + const params = { fields: { api_credentials: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'api_credentials') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].api_credentials(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.api_credentials stop */ + + + /* relationship.versions start */ + it(resourceType + '.versions', async () => { + + const id = TestData.id + const params = { fields: { versions: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken, 'versions') + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].versions(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* relationship.versions stop */ + + +}) diff --git a/specs/resources/user.spec.ts b/specs/resources/user.spec.ts new file mode 100644 index 0000000..7b50822 --- /dev/null +++ b/specs/resources/user.spec.ts @@ -0,0 +1,131 @@ +/** + * ©2024 Commerce Layer Inc. + * Source code generated automatically by SDK codegen + **/ + +import { CommerceLayerProvisioningClient, User } from '../../src' +import { isEqual } from 'lodash' +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { getClient, TestData, CommonData, handleError, interceptRequest, checkCommon, checkCommonData, checkCommonParamsList, checkCommonParams, currentAccessToken, randomValue } from '../../test/common' + + + +let clp: CommerceLayerProvisioningClient + + +beforeAll(async () => { clp = await getClient() }) + + +describe('Users resource', () => { + + const resourceType = 'user' + + + /* spec.update.start */ + it(resourceType + '.update', async () => { + + const attributes = { reference_origin: TestData.reference_origin, metadata: TestData.metadata } + const params = { fields: { [resourceType]: CommonData.paramsFields } } + const resData = { id: TestData.id, ...attributes} + + const intId = clp.addRequestInterceptor((config) => { + if (config.method !== 'get') { + expect(config.method).toBe('patch') + checkCommon(config, resourceType, resData.id, currentAccessToken) + checkCommonData(config, resourceType, attributes, resData.id) + } + return interceptRequest() + }) + + await clp[resourceType].update(resData, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.update.stop */ + + + /* spec.singleton.start */ + it(resourceType + '.singleton', async () => { + + const params = { fields: { [resourceType]: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType) + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].retrieve(params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.singleton.stop */ + + + /* spec.type.start */ + it(resourceType + '.type', async () => { + + const resource = { id: TestData.id, type: resourceType } + expect(clp[resourceType].isUser(resource)).toBeTruthy() + + const type = clp[resourceType].type() + expect(type).toBe(resourceType) + + }) + /* spec.type.stop */ + + + /* spec.relationship.start */ + it(resourceType + '.relationship', async () => { + + const relId = clp[resourceType].relationship(TestData.id) + expect(isEqual(relId, { id: TestData.id, type: resourceType})) + + const relResId = clp[resourceType].relationship({ id: TestData.id, type: resourceType }) + expect(isEqual(relResId, { id: TestData.id, type: resourceType})) + + }) + /* spec.relationship.stop */ + + + /* spec.parse.start */ + it(resourceType + '.parse', async () => { + + const reference = 'myReferenceId' + + const payload = ` + { + "data": { + "id": "AbcdEfgHiL", + "meta": { + "mode": "test", + "organization_id": "myOrgId" + }, + "type": "${resourceType}", + "links": { + "self": "/api/${resourceType}/AbcdEfgHiL" + }, + "attributes": { + "metadata": {}, + "reference": "${reference}", + "created_at": "2023-10-01T05:53:29.296Z", + "updated_at": "2023-10-10T08:52:13.251Z" + } + } + } + ` + + const res = clp[resourceType].parse(payload) as User + + expect(res.type).toBe(resourceType) + expect(res.reference).toBe(reference) + + }) + /* spec.parse.stop */ + + + +}) diff --git a/specs/resources/versions.spec.ts b/specs/resources/versions.spec.ts new file mode 100644 index 0000000..a23b286 --- /dev/null +++ b/specs/resources/versions.spec.ts @@ -0,0 +1,128 @@ +/** + * ©2024 Commerce Layer Inc. + * Source code generated automatically by SDK codegen + **/ + +import { CommerceLayerProvisioningClient, Version } from '../../src' +import { isEqual } from 'lodash' +// eslint-disable-next-line @typescript-eslint/no-unused-vars +import { getClient, TestData, CommonData, handleError, interceptRequest, checkCommon, checkCommonData, checkCommonParamsList, checkCommonParams, currentAccessToken, randomValue } from '../../test/common' + + + +let clp: CommerceLayerProvisioningClient + + +beforeAll(async () => { clp = await getClient() }) + + +describe('Versions resource', () => { + + const resourceType = 'versions' + + + /* spec.retrieve.start */ + it(resourceType + '.retrieve', async () => { + + const id = TestData.id + const params = { fields: {[resourceType]: CommonData.paramsFields } } + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType, id, currentAccessToken) + checkCommonParams(config, params) + return interceptRequest() + }) + + await clp[resourceType].retrieve(id, params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.retrieve.stop */ + + + /* spec.list.start */ + it(resourceType + '.list', async () => { + + const params = CommonData.paramsList + + const intId = clp.addRequestInterceptor((config) => { + expect(config.method).toBe('get') + checkCommon(config, resourceType) + checkCommonParamsList(config, params) + return interceptRequest() + }) + + await clp[resourceType].list(params, CommonData.options) + .catch(handleError) + .finally(() => clp.removeInterceptor('request', intId)) + + }) + /* spec.list.stop */ + + + /* spec.type.start */ + it(resourceType + '.type', async () => { + + const resource = { id: TestData.id, type: resourceType } + expect(clp[resourceType].isVersion(resource)).toBeTruthy() + + const type = clp[resourceType].type() + expect(type).toBe(resourceType) + + }) + /* spec.type.stop */ + + + /* spec.relationship.start */ + it(resourceType + '.relationship', async () => { + + const relId = clp[resourceType].relationship(TestData.id) + expect(isEqual(relId, { id: TestData.id, type: resourceType})) + + const relResId = clp[resourceType].relationship({ id: TestData.id, type: resourceType }) + expect(isEqual(relResId, { id: TestData.id, type: resourceType})) + + }) + /* spec.relationship.stop */ + + + /* spec.parse.start */ + it(resourceType + '.parse', async () => { + + const reference = 'myReferenceId' + + const payload = ` + { + "data": { + "id": "AbcdEfgHiL", + "meta": { + "mode": "test", + "organization_id": "myOrgId" + }, + "type": "${resourceType}", + "links": { + "self": "/api/${resourceType}/AbcdEfgHiL" + }, + "attributes": { + "metadata": {}, + "reference": "${reference}", + "created_at": "2023-10-01T05:53:29.296Z", + "updated_at": "2023-10-10T08:52:13.251Z" + } + } + } + ` + + const res = clp[resourceType].parse(payload) as Version + + expect(res.type).toBe(resourceType) + expect(res.reference).toBe(reference) + + }) + /* spec.parse.stop */ + + + +}) diff --git a/specs/sdk.spec.ts b/specs/sdk.spec.ts new file mode 100644 index 0000000..d1d8b97 --- /dev/null +++ b/specs/sdk.spec.ts @@ -0,0 +1,70 @@ + +import { CommerceLayerProvisioningClient, Role } from '../src' +import { sleep, sortObjectFields } from '../src/util' +import { getClient, TestData } from '../test/common' +import { ObjectType, isResourceType } from '../src/common' + + +let clp: CommerceLayerProvisioningClient + + +// eslint-disable-next-line @typescript-eslint/no-unused-vars +beforeAll(async () => { clp = await getClient() }) + + +describe('SDK suite', () => { + + it('util.sleep', async () => { + + const ms = 2000 + + const start = Date.now() + await sleep(ms) + const stop = Date.now() + + const delay = stop - start + + expect(delay).toBeGreaterThanOrEqual(ms - 10) + expect(delay).toBeLessThan(ms + 50) + + }) + + + it('util.sortObjectFields', async () => { + + const obj: ObjectType = { + beta: 'beta', + delta: 'delta', + alfa: 'alfa', + gamma: 'gamma' + } + + const exp: ObjectType = { + alfa: 'alfa', + beta: 'beta', + gamma: 'gamma', + delta: 'delta' + } + + const sorted = sortObjectFields(obj) + + expect(sorted).toEqual(exp) + + }) + + + it('common.type', async () => { + + const customer: Role = { + id: TestData.id, + type: 'roles', + created_at: new Date().toISOString(), + updated_at: new Date().toISOString(), + name: 'Test Role' + } + + expect(isResourceType(customer)).toBeTruthy() + + }) + +}) diff --git a/specs/static.spec.ts b/specs/static.spec.ts new file mode 100644 index 0000000..a075812 --- /dev/null +++ b/specs/static.spec.ts @@ -0,0 +1,43 @@ + +import { CommerceLayerProvisioningClient, CommerceLayerProvisioningStatic } from '../src' +import { OPEN_API_SCHEMA_VERSION } from '../src/commercelayer' +import { getClient } from '../test/common' + + +let clp: CommerceLayerProvisioningClient + + +beforeAll(async () => { clp = await getClient() }) + + +describe('SDK:static suite', () => { + + it('static.SdkError', async () => { + const sdkError = CommerceLayerProvisioningStatic.isSdkError({ message: 'SdkError', name: 'SdkError', type: 'request' }) + expect(sdkError).toBeTruthy() + }) + + + it('static.ApiError', async () => { + const apiError = CommerceLayerProvisioningStatic.isApiError({ message: 'ApiError', name: 'ApiError', type: 'response' }) + expect(apiError).toBeTruthy() + }) + + + it('static.resources', async () => { + const resources = CommerceLayerProvisioningStatic.resources() + expect(Array.isArray(resources)).toBeTruthy() + }) + + + it('static.init', async () => { + const client = CommerceLayerProvisioningStatic.init({ accessToken: 'fake-access-token' }) + expect(client).not.toBeNull() + }) + + it('static.schema', async () => { + const sver = CommerceLayerProvisioningStatic.schemaVersion + expect(sver).toBe(OPEN_API_SCHEMA_VERSION) + }) + +}) diff --git a/src/api.ts b/src/api.ts new file mode 100644 index 0000000..59e0a39 --- /dev/null +++ b/src/api.ts @@ -0,0 +1,157 @@ + + + + + + + + + 'user' + + 'user' + + + + + + + + + + + + + + + + +import type { Resource, ResourceRel } from './resource' +import type { VersionType } from './resources/versions' + +// ##__API_RESOURCES_START__## +// ##__API_RESOURCES_TEMPLATE:: export { default as ##__RESOURCE_CLASS__## } from './resources/##__RESOURCE_TYPE__##' +/** + * ©2024 Commerce Layer Inc. + **/ +export { default as ApiCredentials } from './resources/api_credentials' +export { default as ApplicationMemberships } from './resources/application_memberships' +export { default as Memberships } from './resources/memberships' +export { default as Organizations } from './resources/organizations' +export { default as Permissions } from './resources/permissions' +export { default as Roles } from './resources/roles' +export { default as Users } from './resources/user' +export { default as Versions } from './resources/versions' +// ##__API_RESOURCES_STOP__## + + +export type ResourceTypeLock = +// ##__API_RESOURCE_TYPES_START__## + 'api_credentials' +| 'application_memberships' +| 'memberships' +| 'organizations' +| 'permissions' +| 'roles' +| 'user' +| 'versions' +// ##__API_RESOURCE_TYPES_STOP__## + + +export const resourceList = [ +// ##__API_RESOURCE_LIST_START__## + 'api_credentials', + 'application_memberships', + 'memberships', + 'organizations', + 'permissions', + 'roles', + 'user', + 'versions' +// ##__API_RESOURCE_LIST_STOP__## +] as const + + +export const singletonList = [ +// ##__API_RESOURCE_SINGLETON_START__## + 'user' +// ##__API_RESOURCE_SINGLETON_STOP__## +] as const + + +// Retrievable resources +export type RetrievableResourceType = ResourceTypeLock + +export type RetrievableResource = Resource & { + type: RetrievableResourceType +} + + +// Listable resources +export type ListableResourceType = Exclude + +export type ListableResource = Resource & { + type: ListableResourceType +} + + +// Creatable resources +export type CreatableResourceType = + // ##__API_RESOURCE_CREATABLE_START__## + 'api_credentials' +| 'application_memberships' +| 'memberships' +| 'organizations' +| 'permissions' +| 'roles' + // ##__API_RESOURCE_CREATABLE_STOP__## + +export type CreatableResource = Resource & { + type: CreatableResourceType +} + + +// Updatable resources +export type UpdatableResourceType = + // ##__API_RESOURCE_UPDATABLE_START__## + 'api_credentials' +| 'application_memberships' +| 'memberships' +| 'organizations' +| 'permissions' +| 'roles' + // ##__API_RESOURCE_UPDATABLE_STOP__## + +export type UpdatableResource = Resource & { + type: UpdatableResourceType +} + + +// Deletable resources +export type DeletableResourceType = + // ##__API_RESOURCE_DELETABLE_START__## + 'api_credentials' +| 'application_memberships' +| 'memberships' + // ##__API_RESOURCE_DELETABLE_STOP__## + +export type DeletableResource = Resource & { + type: DeletableResourceType +} + + +// Versionable resources +export type VersionableResourceType = + // ##__API_RESOURCE_VERSIONABLE_START__## + 'memberships' +| 'permissions' +| 'roles' + // ##__API_RESOURCE_VERSIONABLE_STOP__## + +export type VersionableResource = Resource & { + type: VersionableResourceType, + versions?: Array | null +} diff --git a/src/client.ts b/src/client.ts new file mode 100644 index 0000000..69ccc22 --- /dev/null +++ b/src/client.ts @@ -0,0 +1,214 @@ + +import axios from 'axios' +import type { AxiosAdapter, CreateAxiosDefaults, AxiosInstance, AxiosProxyConfig, Method } from 'axios' +import { SdkError, handleError } from './error' +import type { InterceptorManager } from './interceptor' +import config from './config' +import type { Agent as HttpAgent } from 'http' +import type { Agent as HttpsAgent } from 'https' +// import { packageInfo } from './util' + +import Debug from './debug' +const debug = Debug('client') + + + +const baseURL = (domain?: string): string => { + return `https://provisioning.${domain || config.default.domain}/api` +} + + +type ProxyConfig = AxiosProxyConfig | false +type Adapter = AxiosAdapter + +type RequestParams = Record +type RequestHeaders = Record + +// Subset of AxiosRequestConfig +type RequestConfig = { + timeout?: number + params?: RequestParams + httpAgent?: HttpAgent + httpsAgent?: HttpsAgent + proxy?: ProxyConfig + headers?: RequestHeaders +} + +type RequestConfigExtra = { + adapter?: Adapter + userAgent?: string +} + +type ApiConfig = { + domain?: string, + accessToken: string +} + +type ApiClientInitConfig = ApiConfig & RequestConfig & RequestConfigExtra +type ApiClientConfig = Partial + + +class ApiClient { + + static create(options: ApiClientInitConfig): ApiClient { + for (const attr of config.client.requiredAttributes) + if (!options || !options[attr as keyof ApiClientInitConfig]) throw new SdkError({ message: `Undefined '${attr}' parameter` }) + return new ApiClient(options) + } + + baseUrl: string + #accessToken: string + readonly #client: AxiosInstance + + public interceptors: InterceptorManager + + private constructor(options: ApiClientInitConfig) { + + debug('new client instance %O', options) + + this.baseUrl = baseURL(options.domain) + this.#accessToken = options.accessToken + + const axiosConfig: RequestConfig = { + timeout: options.timeout || config.client.timeout, + proxy: options.proxy, + httpAgent: options.httpAgent, + httpsAgent: options.httpsAgent + } + + // Set custom headers + const customHeaders = this.customHeaders(options.headers) + + // Set headers + const headers: any = { + ...customHeaders, + 'Accept': 'application/vnd.api+json', + 'Content-Type': 'application/vnd.api+json', + 'Authorization': 'Bearer ' + this.#accessToken + } + + // Set User-Agent + let userAgent = options.userAgent // || `SDK-provisioning axios/${axios.VERSION}` + if (userAgent) { + if (!userAgent.includes('axios/')) userAgent += ` axios/${axios.VERSION}` + headers['User-Agent'] = userAgent + } + + const axiosOptions: CreateAxiosDefaults = { + baseURL: this.baseUrl, + timeout: config.client.timeout, + headers, + ...axiosConfig + } + + if (options.adapter) axiosOptions.adapter = options.adapter + + debug('axios options: %O', axiosOptions) + + this.#client = axios.create(axiosOptions) + + this.interceptors = this.#client.interceptors + + } + + + config(config: ApiClientConfig): ApiClient { + + debug('config %o', config) + + const def = this.#client.defaults + + // Axios config + if (config.timeout) def.timeout = config.timeout + if (config.proxy) def.proxy = config.proxy + if (config.httpAgent) def.httpAgent = config.httpAgent + if (config.httpsAgent) def.httpsAgent = config.httpsAgent + + if (config.adapter) this.adapter(config.adapter) + if (config.userAgent) this.userAgent(config.userAgent) + + + // API Client config + if (config.accessToken) { + this.#accessToken = config.accessToken + def.headers.common.Authorization = 'Bearer ' + this.#accessToken; + } + if (config.headers) def.headers.common = this.customHeaders(config.headers) + + return this + + } + + + userAgent(userAgent: string): ApiClient { + if (userAgent) { + let ua = userAgent + if (!ua.includes('axios/')) { + // const axiosVer = packageInfo(['dependencies.axios'], { nestedName: true }) + if (axios.VERSION) ua += ` axios/${axios.VERSION}` + } + this.#client.defaults.headers['User-Agent'] = ua + } + return this + } + + + adapter(adapter: Adapter): ApiClient { + if (adapter) this.#client.defaults.adapter = adapter + return this + } + + + async request(method: Method, path: string, body?: any, options?: ApiClientConfig): Promise { + + debug('request %s %s, %O, %O', method, path, body || {}, options || {}) + + // Ignored params alerts (in debug mode) + if (options?.adapter) debug('Adapter ignored in request config') + if (options?.userAgent) debug('User-Agent header ignored in request config') + + const data = body ? { data: body } : undefined + const url = path + + // Runtime request parameters + const accessToken = options?.accessToken || this.#accessToken + + const headers = this.customHeaders(options?.headers) + if (accessToken) headers.Authorization = 'Bearer ' + accessToken + + const requestParams = { method, url, data, ...options, headers } + + debug('request params: %O', requestParams) + + // const start = Date.now() + return this.#client.request(requestParams) + .then(response => response.data) + .catch((error: Error) => handleError(error)) + // .finally(() => console.log(`<<-- ${method} ${path} ${Date.now() - start}`)) + + } + + + private customHeaders(headers?: RequestHeaders): RequestHeaders { + const customHeaders: RequestHeaders = {} + if (headers) { + for (const [name, value] of Object.entries(headers)) + if (!['accept', 'content-type', 'authorization', 'user-agent'].includes(name.toLowerCase())) customHeaders[name] = value + } + return customHeaders + } + + + /* + get currentAccessToken(): string { + return this.#accessToken + } + */ + +} + + + +export default ApiClient + +export type { ApiClientInitConfig, ApiClientConfig, RequestConfig } diff --git a/src/commercelayer.ts b/src/commercelayer.ts new file mode 100644 index 0000000..71442fc --- /dev/null +++ b/src/commercelayer.ts @@ -0,0 +1,160 @@ + +import * as api from './api' +import type { ApiError } from './error' +import type { ErrorInterceptor, InterceptorType, RawResponseReader, RequestInterceptor, ResponseInterceptor, ResponseObj, HeadersObj } from './interceptor' +import { CommerceLayerProvisioningStatic } from './static' +import ResourceAdapter, { type ResourcesInitConfig } from './resource' + +import Debug from './debug' +const debug = Debug('commercelayer') + + +// Autogenerated schema version number, do not remove this line +const OPEN_API_SCHEMA_VERSION = '1.0.1' +export { OPEN_API_SCHEMA_VERSION } + + +// SDK local configuration +type SdkConfig = { + // abc?: string +} + +type CommerceLayerInitConfig = SdkConfig & ResourcesInitConfig +type CommerceLayerConfig = Partial + + + +class CommerceLayerProvisioningClient { + + // static get openApiSchemaVersion(): string { return OPEN_API_SCHEMA_VERSION } + readonly openApiSchemaVersion = OPEN_API_SCHEMA_VERSION + + readonly #adapter: ResourceAdapter + // #environment: ApiMode = sdkConfig.default.environment + + // ##__CL_RESOURCES_DEF_START__## + // ##__CL_RESOURCES_DEF_TEMPLATE:: ##__TAB__####__RESOURCE_TYPE__##: api.##__RESOURCE_CLASS__## + api_credentials: api.ApiCredentials + application_memberships: api.ApplicationMemberships + memberships: api.Memberships + organizations: api.Organizations + permissions: api.Permissions + roles: api.Roles + user: api.Users + versions: api.Versions + // ##__CL_RESOURCES_DEF_STOP__## + + + constructor(config: CommerceLayerInitConfig) { + + debug('new commercelayer provisioning instance %O', config) + + this.#adapter = new ResourceAdapter(config) + // this.#environment = 'test' + + // ##__CL_RESOURCES_INIT_START__## + // ##__CL_RESOURCES_INIT_TEMPLATE:: ##__TAB__####__TAB__##this.##__RESOURCE_TYPE__## = new api.##__RESOURCE_CLASS__##(this.#adapter) + this.api_credentials = new api.ApiCredentials(this.#adapter) + this.application_memberships = new api.ApplicationMemberships(this.#adapter) + this.memberships = new api.Memberships(this.#adapter) + this.organizations = new api.Organizations(this.#adapter) + this.permissions = new api.Permissions(this.#adapter) + this.roles = new api.Roles(this.#adapter) + this.user = new api.Users(this.#adapter) + this.versions = new api.Versions(this.#adapter) + // ##__CL_RESOURCES_INIT_STOP__## + + } + + // get environment(): ApiMode { return this.#environment } + + + private localConfig(config: SdkConfig): void { + + } + + + config(config: CommerceLayerConfig): CommerceLayerProvisioningClient { + + debug('config %o', config) + + // CommerceLayer config + this.localConfig(config) + // ResourceAdapter config + this.#adapter.config(config) + + return this + + } + + + resources(): readonly string[] { + return CommerceLayerProvisioningStatic.resources() + } + + singletons(): readonly string[] { + return CommerceLayerProvisioningStatic.singletons() + } + + isSingleton(resource: api.ResourceTypeLock): boolean { + return CommerceLayerProvisioningStatic.isSingleton(resource) + } + + + isApiError(error: any): error is ApiError { + return CommerceLayerProvisioningStatic.isApiError(error) + } + + + addRequestInterceptor(onFulfilled?: RequestInterceptor, onRejected?: ErrorInterceptor): number { + return this.#adapter.interceptors.request.use(onFulfilled, onRejected) + } + + addResponseInterceptor(onFulfilled?: ResponseInterceptor, onRejected?: ErrorInterceptor): number { + return this.#adapter.interceptors.response.use(onFulfilled, onRejected) + } + + removeInterceptor(type: InterceptorType, id: number): void { + this.#adapter.interceptors[type].eject(id) + } + + + addRawResponseReader(options?: { headers: boolean }): RawResponseReader { + + const reader: RawResponseReader = { + id: undefined, + rawResponse: undefined, + headers: undefined, + } + + function rawResponseInterceptor(response: ResponseObj): ResponseObj { + reader.rawResponse = response?.data + if (options?.headers) reader.headers = (response.headers as HeadersObj) + return response + } + + const interceptor = this.addResponseInterceptor(rawResponseInterceptor) + reader.id = interceptor + + return reader + + } + + removeRawResponseReader(reader: number | RawResponseReader): void { + const id = (typeof reader === 'number') ? reader : reader?.id + if (id && (id >= 0)) this.removeInterceptor('response', id) + } + +} + + + +const CommerceLayerProvisioning = (config: CommerceLayerInitConfig): CommerceLayerProvisioningClient => { + return new CommerceLayerProvisioningClient(config) +} + + +export default CommerceLayerProvisioning +export { CommerceLayerProvisioning } + +export type { CommerceLayerProvisioningClient, CommerceLayerConfig, CommerceLayerInitConfig } diff --git a/src/common.ts b/src/common.ts new file mode 100644 index 0000000..25d9249 --- /dev/null +++ b/src/common.ts @@ -0,0 +1,17 @@ + +import { type ResourceTypeLock, resourceList } from './api' +import type { ResourceId, ResourceType } from './resource' + +const isResourceId = (resource: any): resource is ResourceId => { + return (resource?.type && resource.id) && resourceList.includes(resource.type as ResourceTypeLock) +} + +const isResourceType = (resource: any): resource is ResourceType => { + return resource && (typeof resource.type !== 'undefined') && resource.type && resourceList.includes(resource.type as ResourceTypeLock) +} + + +export { isResourceId, isResourceType } + + +export type ObjectType = Record diff --git a/src/config.ts b/src/config.ts new file mode 100644 index 0000000..d091abc --- /dev/null +++ b/src/config.ts @@ -0,0 +1,18 @@ +// export type ApiMode = 'test' | 'live' + + +const config = { + default: { + // environment: 'test', + domain: 'commercelayer.io', + pageNumber: 1, + pageSize: 10, + }, + client: { + timeout: 15000, + requiredAttributes: ['accessToken'], + } +} as const + + +export default config diff --git a/src/debug.ts b/src/debug.ts new file mode 100644 index 0000000..75f8e35 --- /dev/null +++ b/src/debug.ts @@ -0,0 +1,51 @@ + +type Debugger = (pattern: string, ...args: any[]) => void + +type DebuggerFactory = (namespace: string) => Debugger + + +/* Nope debugger */ +const debuggerFunction = (_pattern: string, ..._args: any[]): void => { + // console.log(_pattern) +} + +let debuggerFactory: DebuggerFactory = (_namespace: string): Debugger => debuggerFunction + + +/* Try loading 'debug' module */ +try { + const debugModule = require('debug') + if (debugModule && (typeof debugModule === 'function')) debuggerFactory = debugModule +} catch (error) { + // +} + + +const debugPrefix = 'clsdk' + + +/* Retrieve the name of the caller 'module' */ +/* +const caller = (): string => { + + const err = new Error() + + Error.prepareStackTrace = (_, stack) => stack + const stack = err.stack as unknown as NodeJS.CallSite[] + Error.prepareStackTrace = undefined + + const fileName = stack[2].getFileName() || '/' + + return fileName.replace(/^.*[\\/]/, '').replace('.ts', '') + +} +*/ + + +/* Return a debugger for the defined namespace */ +const debug = (namespace: string): Debugger => { + return debuggerFactory(`${debugPrefix}:${namespace}`) +} + + +export default debug diff --git a/src/error.ts b/src/error.ts new file mode 100644 index 0000000..73ec7e7 --- /dev/null +++ b/src/error.ts @@ -0,0 +1,92 @@ +import axios from 'axios' + +enum ErrorType { + CLIENT = 'client', // Error instantiating the client + REQUEST = 'request', // Error preparing API request + RESPONSE = 'response', // Error response from API + CANCEL = 'cancel', // Forced request abort using interceptor + PARSE = 'parse', // Error parsing API resource + GENERIC = 'generic', // Other not specified errors +} + + +class SdkError extends Error { + + static NAME = 'SdkError' + + static isSdkError(error: any): error is SdkError { + return error && [SdkError.NAME, ApiError.NAME].includes(error.name as string) && Object.values(ErrorType).includes(error.type as ErrorType) + } + + type: ErrorType + code?: string + source?: Error + request?: any + + constructor(error: { message: string, type?: ErrorType }) { + super(error.message) + this.name = SdkError.NAME// this.constructor.name + this.type = error.type || ErrorType.GENERIC + } + +} + +class ApiError extends SdkError { + + static NAME = 'ApiError' + + static isApiError(error: any): error is ApiError { + return SdkError.isSdkError(error) && (error.name === ApiError.NAME) && (error.type === ErrorType.RESPONSE) + } + + errors: any[] = [] + status?: number + statusText?: string + + constructor(error: SdkError) + constructor(error: { message: string }) { + super({ ...error, type: ErrorType.RESPONSE }) + this.name = ApiError.NAME// this.constructor.name + } + + first(): any { + return (this.errors?.length > 0) ? this.errors[0] : undefined + } + +} + + + +const handleError = (error: Error): never => { + + let sdkError = new SdkError({ message: error.message }) + + if (axios.isAxiosError(error)) { + if (error.response) { + // The request was made and the server responded with a status code that falls out of the range of 2xx + const apiError = new ApiError(sdkError) + apiError.type = ErrorType.RESPONSE + apiError.status = error.response.status + apiError.statusText = error.response.statusText + apiError.code = String(apiError.status) + apiError.errors = error.response.data.errors + if (!apiError.message && apiError.statusText) apiError.message = apiError.statusText + sdkError = apiError + } else if (error.request) { + // The request was made but no response was received + // `error.request` is an instance of XMLHttpRequest in the browser and an instance of http.ClientRequest in node.js + sdkError.type = ErrorType.REQUEST + sdkError.request = error.request + } else { + // Something happened in setting up the request that triggered an Error + sdkError.type = ErrorType.CLIENT + } + } else if (axios.isCancel(error)) sdkError.type = ErrorType.CANCEL + else sdkError.source = error + + throw sdkError + +} + + +export { SdkError, ApiError, ErrorType, handleError } diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..ae4bf6f --- /dev/null +++ b/src/index.ts @@ -0,0 +1,21 @@ + +// SDK +export { default, CommerceLayerProvisioning } from './commercelayer' + +// Commerce Layer Provisioning client type +export type { CommerceLayerProvisioningClient } from './commercelayer' + +// Commerce Layer Provisioning static functions +export { CommerceLayerProvisioningStatic } from './static' + +// Query filter types +export type { QueryParamsRetrieve, QueryParamsList, QueryParams } from './query' + +// Resource model types +export type * from './model' + +// Raw response reader and request/response interceptors +export type { RequestObj, ResponseObj, ErrorObj, HeadersObj } from './interceptor' + +// Error types +export type { SdkError, ApiError, ErrorType } from './error' diff --git a/src/interceptor.ts b/src/interceptor.ts new file mode 100644 index 0000000..2422b53 --- /dev/null +++ b/src/interceptor.ts @@ -0,0 +1,43 @@ + +import type { AxiosError, AxiosInterceptorManager, AxiosRequestConfig, AxiosResponse, AxiosResponseHeaders, RawAxiosResponseHeaders } from 'axios' + + +type InterceptorManager = { + request: AxiosInterceptorManager; + response: AxiosInterceptorManager +} + + +// Request +type RequestObj = AxiosRequestConfig +type RequestInterceptor = (request: RequestObj) => RequestObj | Promise + +// Response +type ResponseObj = AxiosResponse +type ResponseInterceptor = (response: ResponseObj) => ResponseObj + +// Headers +type ApiHeadersList = 'x-ratelimit-limit' | 'x-ratelimit-count' | 'x-ratelimit-period' | 'x-ratelimit-interval' | 'x-ratelimit-remaining' +type ApiHeaders = { [key in ApiHeadersList]: string | number | boolean } +type HeadersObj = (AxiosResponseHeaders | RawAxiosResponseHeaders) & ApiHeaders + + +type ErrorObj = AxiosError +type ErrorInterceptor = (error: ErrorObj) => ErrorObj + +type InterceptorType = 'request' | 'response' + + +export type { InterceptorManager, RequestInterceptor, ResponseInterceptor, ErrorInterceptor, InterceptorType } +export type { RequestObj, ResponseObj, ErrorObj, HeadersObj } + + + +type RawResponseReader = { + id: number | undefined; + rawResponse: ResponseObj | undefined; + headers: HeadersObj | undefined; +} + + +export type { RawResponseReader } diff --git a/src/jsonapi.ts b/src/jsonapi.ts new file mode 100644 index 0000000..9c2ae8d --- /dev/null +++ b/src/jsonapi.ts @@ -0,0 +1,113 @@ + +import type { Value as JSONValue } from 'json-typescript' +import type { DocWithData, Included, ResourceIdentifierObject, ResourceObject as JSONAPIObject, AttributesObject, RelationshipsObject } from 'jsonapi-typescript' +import type { ResourceCreate, ResourceUpdate, ResourceId, ResourceType, Resource, ResourceRel } from './resource' +import { isResourceId, isResourceType } from './common' + +import Debug from './debug' +const debug = Debug('jsonapi') + +export type { DocWithData } + + + +// DENORMALIZATION + +const denormalize = (response: DocWithData): R | R[] => { + + let denormalizedResponse + + if (response.links) delete response.links + + const data = response.data + const included = response.included + + if (!data) denormalizedResponse = data + else { + if (Array.isArray(data)) denormalizedResponse = data.map(res => denormalizeResource(res, included)) + else denormalizedResponse = denormalizeResource(data, included) + } + + return denormalizedResponse + +} + + +const findIncluded = (rel: ResourceIdentifierObject, included: Included = []): JSONAPIObject | undefined => { + const inc = included.find(inc => { + return (rel.id === inc.id) && (rel.type === inc.type) + }) + return inc || rel +} + + +const denormalizeResource = (res: any, included?: Included): T => { + + debug('denormalize resource: %O, %o', res, included || {}) + + if (!res) return res + + const resource = { + id: res.id, + type: res.type, + ...res.attributes, + } + + if (res.relationships) Object.keys(res.relationships as object).forEach(key => { + const rel: ResourceIdentifierObject = res.relationships[key].data + if (rel) { + if (Array.isArray(rel)) resource[key] = rel.map((r: ResourceIdentifierObject) => denormalizeResource(findIncluded(r, included), included)) + else resource[key] = denormalizeResource(findIncluded(rel, included), included) + } else if (rel === null) resource[key] = null + }) + + debug('denormalized resource: %O', resource) + + return resource + +} + + +// NORMALIZATION + +const normalize = (resource: (ResourceCreate & ResourceType) | (ResourceUpdate & ResourceId)): JSONAPIObject => { + + debug('normalize resource: %O', resource) + + const attributes: AttributesObject = {} + const relationships: RelationshipsObject = {} + + for (const field in resource) { + if (['type', 'id'].includes(field)) continue + const value = resource[field as keyof (ResourceCreate | ResourceUpdate)] + if (Array.isArray(value) && (value.length === 1) && isResourceType(value[0]) && ((value[0] as ResourceRel).id === null)) { + relationships[field] = { data: [] } + } + else + if (value && isResourceType(value) && ((value as ResourceRel).id === null)) { + relationships[field] = { data: null } + } + else + if (value && (isResourceId(value) || (Array.isArray(value) && isResourceId(value[0])))) { + relationships[field] = { data: value as ResourceIdentifierObject } + } + else attributes[field] = value as JSONValue + } + + const normalized: JSONAPIObject = { + type: resource.type, + attributes, + relationships + } + + if (isResourceId(resource)) normalized.id = resource.id + + debug('normalized resource: %O', normalized) + + return normalized + +} + + + +export { denormalize, normalize } diff --git a/src/model.ts b/src/model.ts new file mode 100644 index 0000000..769028f --- /dev/null +++ b/src/model.ts @@ -0,0 +1,15 @@ + +// ##__MODEL_TYPES_START__## +// ##__MODEL_TYPES_TEMPLATE:: export type { ##__RESOURCE_MODELS__## } from './resources/##__RESOURCE_TYPE__##' +/** + * ©2024 Commerce Layer Inc. + **/ +export type { ApiCredential, ApiCredentialCreate, ApiCredentialUpdate } from './resources/api_credentials' +export type { ApplicationMembership, ApplicationMembershipCreate, ApplicationMembershipUpdate } from './resources/application_memberships' +export type { Membership, MembershipCreate, MembershipUpdate } from './resources/memberships' +export type { Organization, OrganizationCreate, OrganizationUpdate } from './resources/organizations' +export type { Permission, PermissionCreate, PermissionUpdate } from './resources/permissions' +export type { Role, RoleCreate, RoleUpdate } from './resources/roles' +export type { User, UserUpdate } from './resources/user' +export type { Version } from './resources/versions' +// ##__MODEL_TYPES_STOP__## \ No newline at end of file diff --git a/src/query.ts b/src/query.ts new file mode 100644 index 0000000..483ee36 --- /dev/null +++ b/src/query.ts @@ -0,0 +1,76 @@ + +import type { ResourceType } from "./resource" + +import Debug from './debug' +const debug = Debug('query') + + +type QueryFilter = Record + + +interface QueryParamsRetrieve { + include?: string[] + fields?: string[] | Record +} + + +interface QueryParamsList extends QueryParamsRetrieve { + sort?: string[] | Record + filters?: QueryFilter + pageNumber?: number + pageSize?: number +} + +type QueryParams = QueryParamsRetrieve | QueryParamsList + +export type { QueryParamsRetrieve, QueryParamsList, QueryParams, QueryFilter } + + + +const isParamsList = (params: any): params is QueryParamsList => { + return params && (params.filters || params.pageNumber || params.pageSize || params.sort) +} + + +const generateQueryStringParams = (params: QueryParamsRetrieve | QueryParamsList | undefined, res: string | ResourceType): Record => { + + debug('generate query string params: %O, %O', params, res) + + const qp: Record = {} + if (!params) return qp + + // Include + if (params.include) qp.include = params.include.join(',') + // Fields + if (params.fields) { + if (Array.isArray(params.fields)) params.fields = { [(res as ResourceType).type || res]: params.fields } + Object.entries(params.fields).forEach(([p, v]) => { + qp[`fields[${p}]`] = v.join(',') + }) + } + + if (isParamsList(params)) { + // Sort + if (params.sort) { + if (Array.isArray(params.sort)) qp.sort = params.sort.join(',') + else qp.sort = Object.entries(params.sort).map(([k, v]) => `${v === 'desc' ? '-' : ''}${k}`).join(',') + } + // Page + if (params.pageNumber) qp['page[number]'] = String(params.pageNumber) + if (params.pageSize) qp['page[size]'] = String(params.pageSize) + // Filters + if (params.filters) { + Object.entries(params.filters).forEach(([p, v]) => { + qp[`filter[q][${p}]`] = String(v) + }) + } + } + + debug('query string params: %O', qp) + + return qp + +} + + +export { generateQueryStringParams, isParamsList } diff --git a/src/resource.ts b/src/resource.ts new file mode 100644 index 0000000..ef187be --- /dev/null +++ b/src/resource.ts @@ -0,0 +1,333 @@ + +import ApiClient, { type ApiClientInitConfig } from './client' +import { denormalize, normalize, type DocWithData } from './jsonapi' +import type { QueryParamsRetrieve, QueryParamsList, QueryFilter, QueryParams } from './query' +import { generateQueryStringParams, isParamsList } from './query' +import type { ResourceTypeLock } from './api' +import config from './config' +import type { InterceptorManager } from './interceptor' +import { ErrorType, SdkError } from './error' +import { CommerceLayerProvisioningStatic } from './static' + +import Debug from './debug' +const debug = Debug('resource') + + + +type ResourceNull = { id: null } & ResourceType +type ResourceRel = ResourceId | ResourceNull + + +type Metadata = Record + + +interface ResourceType { + readonly type: ResourceTypeLock +} + + +interface ResourceId extends ResourceType { + readonly id: string +} + + +interface ResourceBase { + reference?: string | null + reference_origin?: string | null + metadata?: Metadata +} + + +interface Resource extends ResourceBase, ResourceId { + readonly created_at: string + readonly updated_at: string +} + + +interface ResourceCreate extends ResourceBase { + +} + + +interface ResourceUpdate extends ResourceBase { + readonly id: string +} + + +type ListMeta = { + readonly pageCount: number + readonly recordCount: number + readonly currentPage: number + readonly recordsPerPage: number +} + +class ListResponse extends Array { + + readonly meta: ListMeta + + constructor(meta: ListMeta, data: R[]) { + super(...(data || [])) + this.meta = meta + } + + first(): R | undefined { return this.length ? this[0] : undefined } + last(): R | undefined { return this.length ? this[this.length - 1] : undefined } + get(index: number): R | undefined { return (this.length && (index >= 0)) ? this[index] : undefined } + + hasNextPage(): boolean { return (this.meta.currentPage < this.meta.pageCount) } + hasPrevPage(): boolean { return (this.meta.currentPage > 1) } + + getRecordCount(): number { return this.meta.recordCount } + getPageCount(): number { return this.meta.pageCount } + get recordCount(): number { return this.meta.recordCount } + get pageCount(): number { return this.meta.pageCount } + +} + + + +export type { Metadata, ResourceType, ResourceId, Resource, ResourceCreate, ResourceUpdate, ListResponse, ListMeta, ResourceRel } + + +// Resource adapters local configuration +type ResourceAdapterConfig = { + // xyz?: boolean +} + +type ResourcesInitConfig = ResourceAdapterConfig & ApiClientInitConfig +type ResourcesConfig = Partial + + +class ResourceAdapter { + + readonly #client: ApiClient + + readonly #config: ResourceAdapterConfig = {} + + + constructor(config: ResourcesInitConfig) { + this.#client = ApiClient.create(config) + this.localConfig(config) + } + + + get interceptors(): InterceptorManager { return this.#client.interceptors } + + + private localConfig(config: ResourceAdapterConfig): void { + // if (typeof config.xyz !== 'undefined') this.#config.xyz = config.xyz + } + + + config(config: ResourcesConfig): ResourceAdapter { + + debug('config %o', config) + + // ResourceAdapter config + this.localConfig(config) + // Client config + this.#client.config(config) + + return this + + } + + + /* + get clientInstance(): ApiClient { + return this.#client + } + */ + + + + async retrieve(resource: ResourceId | ResourceType, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + + const singleton = !('id' in resource) || CommerceLayerProvisioningStatic.isSingleton(resource.type) + + debug('retrieve:%s %o, %O, %O', (singleton? ' singleton,' : ''), resource, params || {}, options || {}) + + const queryParams = generateQueryStringParams(params, resource) + if (options?.params) Object.assign(queryParams, options?.params) + + const path = `${resource.type}${singleton? '' : `/${resource.id}`}` + + const res: DocWithData = await this.#client.request('get', path, undefined, { ...options, params: queryParams }) + const r = denormalize(res) as R + + return r + + } + + + async list(resource: ResourceType, params?: QueryParamsList, options?: ResourcesConfig): Promise> { + + debug('list: %o, %O, %O', resource, params || {}, options || {}) + + const queryParams = generateQueryStringParams(params, resource) + if (options?.params) Object.assign(queryParams, options?.params) + + const res: DocWithData = await this.#client.request('get', `${resource.type}`, undefined, { ...options, params: queryParams }) + const r = denormalize(res) as R[] + + const meta: ListMeta = { + pageCount: Number(res.meta?.page_count), + recordCount: Number(res.meta?.record_count), + currentPage: params?.pageNumber || config.default.pageNumber, + recordsPerPage: params?.pageSize || config.default.pageSize + } + + return new ListResponse(meta, r) + + } + + + async create(resource: C & ResourceType, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + + debug('create: %o, %O, %O', resource, params || {}, options || {}) + + const queryParams = generateQueryStringParams(params, resource) + if (options?.params) Object.assign(queryParams, options?.params) + + const data = normalize(resource) + const res: DocWithData = await this.#client.request('post', resource.type, data, { ...options, params: queryParams }) + const r = denormalize(res) as R + + return r + + } + + + async update(resource: U & ResourceId, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + + const singleton = !('id' in resource) || CommerceLayerProvisioningStatic.isSingleton(resource.type) + + debug('update:%s %o, %O, %O', (singleton? ' singleton,' : ''), resource, params || {}, options || {}) + + const queryParams = generateQueryStringParams(params, resource) + if (options?.params) Object.assign(queryParams, options?.params) + + const path = `${resource.type}${singleton? '' : `/${resource.id}`}` + + const data = normalize(resource) + const res: DocWithData = await this.#client.request('patch', path, data, { ...options, params: queryParams }) + const r = denormalize(res) as R + + return r + + } + + + async delete(resource: ResourceId, options?: ResourcesConfig): Promise { + debug('delete: %o, %O', resource, options || {}) + await this.#client.request('delete', `${resource.type}/${resource.id}`, undefined, options) + } + + + async fetch(resource: string | ResourceType, path: string, params?: QueryParams, options?: ResourcesConfig): Promise> { + + debug('fetch: %o, %O, %O', path, params || {}, options || {}) + + const queryParams = generateQueryStringParams(params, resource) + if (options?.params) Object.assign(queryParams, options?.params) + + const res: DocWithData = await this.#client.request('get', path, undefined, { ...options, params: queryParams }) + const r = denormalize(res) + + if (Array.isArray(r)) { + const p = params as QueryParamsList + const meta: ListMeta = { + pageCount: Number(res.meta?.page_count), + recordCount: Number(res.meta?.record_count), + currentPage: p?.pageNumber || config.default.pageNumber, + recordsPerPage: p?.pageSize || config.default.pageSize + } + return new ListResponse(meta, r) + } + else return r + + } + + + async action(cmd: 'post' | 'patch', path: string, payload?: any, options?: ResourcesConfig): Promise { + + debug('action: %o %o, %O', cmd, path, options || {}) + + const queryParams = {} + if (options?.params) Object.assign(queryParams, options?.params) + + await this.#client.request(cmd, path, payload, { ...options, params: queryParams }) + + } + +} + + + +abstract class ApiResourceBase { + + static readonly TYPE: ResourceTypeLock + protected readonly resources: ResourceAdapter + + constructor(adapter: ResourceAdapter) { + debug('new resource instance: %s', this.type()) + this.resources = adapter + } + + abstract relationship(id: string | ResourceId | null): ResourceRel + + abstract type(): ResourceTypeLock + + parse(resource: string): R | R[] { + try { + const res = JSON.parse(resource) + if (res.data?.type !== this.type()) throw new SdkError({ message: `Invalid resource type [${res.data?.type}]`, type: ErrorType.PARSE }) + return denormalize(res as DocWithData) + } catch (error: any) { + if (SdkError.isSdkError(error)) throw error + else throw new SdkError({ message: `Payload parse error [${error.message}]`, type: ErrorType.PARSE }) + } + } + + + // reference, reference_origin and metadata attributes are always updatable + async update(resource: ResourceUpdate, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + return this.resources.update({ ...resource, type: this.type() }, params, options) + } + +} + + +abstract class ApiResource extends ApiResourceBase { + + async retrieve(id: string | ResourceId, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + return this.resources.retrieve((typeof id === 'string') ? { type: this.type(), id } : id, params, options) + } + + async list(params?: QueryParamsList, options?: ResourcesConfig): Promise> { + return this.resources.list({ type: this.type() }, params, options) + } + + async count(filter?: QueryFilter | QueryParamsList, options?: ResourcesConfig): Promise { + const params: QueryParamsList = { filters: isParamsList(filter) ? filter.filters : filter, pageNumber: 1, pageSize: 1 } + const response = await this.list(params, options) + return Promise.resolve(response.meta.recordCount) + } + +} + + +abstract class ApiSingleton extends ApiResourceBase { + + async retrieve(params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + return this.resources.retrieve({ type: this.type() }, params, options) + } + +} + + + +export default ResourceAdapter + +export { ApiResource, ApiSingleton } +export type { ResourcesConfig, ResourcesInitConfig } diff --git a/src/resources/api_credentials.ts b/src/resources/api_credentials.ts new file mode 100644 index 0000000..4c18767 --- /dev/null +++ b/src/resources/api_credentials.ts @@ -0,0 +1,108 @@ +import { ApiResource } from '../resource' +import type { Resource, ResourceCreate, ResourceUpdate, ResourceId, ResourcesConfig, ResourceRel } from '../resource' +import type { QueryParamsRetrieve } from '../query' + +import type { Organization, OrganizationType } from './organizations' +import type { Role, RoleType } from './roles' + + +type ApiCredentialType = 'api_credentials' +type ApiCredentialRel = ResourceRel & { type: ApiCredentialType } +type OrganizationRel = ResourceRel & { type: OrganizationType } +type RoleRel = ResourceRel & { type: RoleType } + + +interface ApiCredential extends Resource { + + readonly type: ApiCredentialType + + name: string + kind: string + confidential: boolean + redirect_uri?: string | null + client_id: string + client_secret: string + scopes: string + expires_in?: number | null + mode?: string | null + custom?: boolean | null + + organization?: Organization | null + role?: Role | null + +} + + +interface ApiCredentialCreate extends ResourceCreate { + + name: string + kind: string + redirect_uri?: string | null + expires_in?: number | null + mode?: string | null + custom?: boolean | null + + organization: OrganizationRel + role?: RoleRel | null + +} + + +interface ApiCredentialUpdate extends ResourceUpdate { + + name?: string | null + redirect_uri?: string | null + expires_in?: number | null + + role?: RoleRel | null + +} + + +class ApiCredentials extends ApiResource { + + static readonly TYPE: ApiCredentialType = 'api_credentials' as const + + async create(resource: ApiCredentialCreate, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + return this.resources.create({ ...resource, type: ApiCredentials.TYPE }, params, options) + } + + async update(resource: ApiCredentialUpdate, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + return this.resources.update({ ...resource, type: ApiCredentials.TYPE }, params, options) + } + + async delete(id: string | ResourceId, options?: ResourcesConfig): Promise { + await this.resources.delete((typeof id === 'string')? { id, type: ApiCredentials.TYPE } : id, options) + } + + async organization(apiCredentialId: string | ApiCredential, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + const _apiCredentialId = (apiCredentialId as ApiCredential).id || apiCredentialId as string + return this.resources.fetch({ type: 'organizations' }, `api_credentials/${_apiCredentialId}/organization`, params, options) as unknown as Organization + } + + async role(apiCredentialId: string | ApiCredential, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + const _apiCredentialId = (apiCredentialId as ApiCredential).id || apiCredentialId as string + return this.resources.fetch({ type: 'roles' }, `api_credentials/${_apiCredentialId}/role`, params, options) as unknown as Role + } + + + isApiCredential(resource: any): resource is ApiCredential { + return resource.type && (resource.type === ApiCredentials.TYPE) + } + + + relationship(id: string | ResourceId | null): ApiCredentialRel { + return ((id === null) || (typeof id === 'string')) ? { id, type: ApiCredentials.TYPE } : { id: id.id, type: ApiCredentials.TYPE } + } + + + type(): ApiCredentialType { + return ApiCredentials.TYPE + } + +} + + +export default ApiCredentials + +export type { ApiCredential, ApiCredentialCreate, ApiCredentialUpdate, ApiCredentialType } diff --git a/src/resources/application_memberships.ts b/src/resources/application_memberships.ts new file mode 100644 index 0000000..acf38e8 --- /dev/null +++ b/src/resources/application_memberships.ts @@ -0,0 +1,110 @@ +import { ApiResource } from '../resource' +import type { Resource, ResourceCreate, ResourceUpdate, ResourceId, ResourcesConfig, ResourceRel } from '../resource' +import type { QueryParamsRetrieve } from '../query' + +import type { ApiCredential, ApiCredentialType } from './api_credentials' +import type { Membership, MembershipType } from './memberships' +import type { Organization, OrganizationType } from './organizations' +import type { Role, RoleType } from './roles' + + +type ApplicationMembershipType = 'application_memberships' +type ApplicationMembershipRel = ResourceRel & { type: ApplicationMembershipType } +type ApiCredentialRel = ResourceRel & { type: ApiCredentialType } +type MembershipRel = ResourceRel & { type: MembershipType } +type OrganizationRel = ResourceRel & { type: OrganizationType } +type RoleRel = ResourceRel & { type: RoleType } + + +interface ApplicationMembership extends Resource { + + readonly type: ApplicationMembershipType + + filters?: Record | null + + api_credential?: ApiCredential | null + membership?: Membership | null + organization?: Organization | null + role?: Role | null + +} + + +interface ApplicationMembershipCreate extends ResourceCreate { + + filters?: Record | null + + api_credential: ApiCredentialRel + membership: MembershipRel + organization: OrganizationRel + role: RoleRel + +} + + +interface ApplicationMembershipUpdate extends ResourceUpdate { + + filters?: Record | null + + role?: RoleRel | null + +} + + +class ApplicationMemberships extends ApiResource { + + static readonly TYPE: ApplicationMembershipType = 'application_memberships' as const + + async create(resource: ApplicationMembershipCreate, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + return this.resources.create({ ...resource, type: ApplicationMemberships.TYPE }, params, options) + } + + async update(resource: ApplicationMembershipUpdate, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + return this.resources.update({ ...resource, type: ApplicationMemberships.TYPE }, params, options) + } + + async delete(id: string | ResourceId, options?: ResourcesConfig): Promise { + await this.resources.delete((typeof id === 'string')? { id, type: ApplicationMemberships.TYPE } : id, options) + } + + async api_credential(applicationMembershipId: string | ApplicationMembership, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + const _applicationMembershipId = (applicationMembershipId as ApplicationMembership).id || applicationMembershipId as string + return this.resources.fetch({ type: 'api_credentials' }, `application_memberships/${_applicationMembershipId}/api_credential`, params, options) as unknown as ApiCredential + } + + async membership(applicationMembershipId: string | ApplicationMembership, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + const _applicationMembershipId = (applicationMembershipId as ApplicationMembership).id || applicationMembershipId as string + return this.resources.fetch({ type: 'memberships' }, `application_memberships/${_applicationMembershipId}/membership`, params, options) as unknown as Membership + } + + async organization(applicationMembershipId: string | ApplicationMembership, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + const _applicationMembershipId = (applicationMembershipId as ApplicationMembership).id || applicationMembershipId as string + return this.resources.fetch({ type: 'organizations' }, `application_memberships/${_applicationMembershipId}/organization`, params, options) as unknown as Organization + } + + async role(applicationMembershipId: string | ApplicationMembership, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + const _applicationMembershipId = (applicationMembershipId as ApplicationMembership).id || applicationMembershipId as string + return this.resources.fetch({ type: 'roles' }, `application_memberships/${_applicationMembershipId}/role`, params, options) as unknown as Role + } + + + isApplicationMembership(resource: any): resource is ApplicationMembership { + return resource.type && (resource.type === ApplicationMemberships.TYPE) + } + + + relationship(id: string | ResourceId | null): ApplicationMembershipRel { + return ((id === null) || (typeof id === 'string')) ? { id, type: ApplicationMemberships.TYPE } : { id: id.id, type: ApplicationMemberships.TYPE } + } + + + type(): ApplicationMembershipType { + return ApplicationMemberships.TYPE + } + +} + + +export default ApplicationMemberships + +export type { ApplicationMembership, ApplicationMembershipCreate, ApplicationMembershipUpdate, ApplicationMembershipType } diff --git a/src/resources/memberships.ts b/src/resources/memberships.ts new file mode 100644 index 0000000..5ecb467 --- /dev/null +++ b/src/resources/memberships.ts @@ -0,0 +1,116 @@ +import { ApiResource } from '../resource' +import type { Resource, ResourceCreate, ResourceUpdate, ResourceId, ResourcesConfig, ResourceRel, ListResponse } from '../resource' +import type { QueryParamsRetrieve, QueryParamsList } from '../query' + +import type { Organization, OrganizationType } from './organizations' +import type { Role, RoleType } from './roles' +import type { ApplicationMembership, ApplicationMembershipType } from './application_memberships' +import type { Version } from './versions' + + +type MembershipType = 'memberships' +type MembershipRel = ResourceRel & { type: MembershipType } +type OrganizationRel = ResourceRel & { type: OrganizationType } +type RoleRel = ResourceRel & { type: RoleType } +type ApplicationMembershipRel = ResourceRel & { type: ApplicationMembershipType } + + +interface Membership extends Resource { + + readonly type: MembershipType + + user_email: string + user_first_name: string + user_last_name: string + status: 'pending' | 'active' + owner: boolean + + organization?: Organization | null + role?: Role | null + application_memberships?: ApplicationMembership[] | null + versions?: Version[] | null + +} + + +interface MembershipCreate extends ResourceCreate { + + user_email: string + + organization: OrganizationRel + role: RoleRel + application_memberships?: ApplicationMembershipRel[] | null + +} + + +interface MembershipUpdate extends ResourceUpdate { + + role?: RoleRel | null + application_memberships?: ApplicationMembershipRel[] | null + +} + + +class Memberships extends ApiResource { + + static readonly TYPE: MembershipType = 'memberships' as const + + async create(resource: MembershipCreate, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + return this.resources.create({ ...resource, type: Memberships.TYPE }, params, options) + } + + async update(resource: MembershipUpdate, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + return this.resources.update({ ...resource, type: Memberships.TYPE }, params, options) + } + + async delete(id: string | ResourceId, options?: ResourcesConfig): Promise { + await this.resources.delete((typeof id === 'string')? { id, type: Memberships.TYPE } : id, options) + } + + async resend(membershipId: string | Membership, options?: ResourcesConfig): Promise { + const _membershipId = (membershipId as Membership).id || membershipId as string + await this.resources.action('post', `memberships/${_membershipId}/resend`, {}, options) + } + + async organization(membershipId: string | Membership, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + const _membershipId = (membershipId as Membership).id || membershipId as string + return this.resources.fetch({ type: 'organizations' }, `memberships/${_membershipId}/organization`, params, options) as unknown as Organization + } + + async role(membershipId: string | Membership, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + const _membershipId = (membershipId as Membership).id || membershipId as string + return this.resources.fetch({ type: 'roles' }, `memberships/${_membershipId}/role`, params, options) as unknown as Role + } + + async application_memberships(membershipId: string | Membership, params?: QueryParamsList, options?: ResourcesConfig): Promise> { + const _membershipId = (membershipId as Membership).id || membershipId as string + return this.resources.fetch({ type: 'application_memberships' }, `memberships/${_membershipId}/application_memberships`, params, options) as unknown as ListResponse + } + + async versions(membershipId: string | Membership, params?: QueryParamsList, options?: ResourcesConfig): Promise> { + const _membershipId = (membershipId as Membership).id || membershipId as string + return this.resources.fetch({ type: 'versions' }, `memberships/${_membershipId}/versions`, params, options) as unknown as ListResponse + } + + + isMembership(resource: any): resource is Membership { + return resource.type && (resource.type === Memberships.TYPE) + } + + + relationship(id: string | ResourceId | null): MembershipRel { + return ((id === null) || (typeof id === 'string')) ? { id, type: Memberships.TYPE } : { id: id.id, type: Memberships.TYPE } + } + + + type(): MembershipType { + return Memberships.TYPE + } + +} + + +export default Memberships + +export type { Membership, MembershipCreate, MembershipUpdate, MembershipType } diff --git a/src/resources/organizations.ts b/src/resources/organizations.ts new file mode 100644 index 0000000..73124cb --- /dev/null +++ b/src/resources/organizations.ts @@ -0,0 +1,142 @@ +import { ApiResource } from '../resource' +import type { Resource, ResourceCreate, ResourceUpdate, ResourceId, ResourcesConfig, ResourceRel, ListResponse } from '../resource' +import type { QueryParamsRetrieve, QueryParamsList } from '../query' + +import type { Membership } from './memberships' +import type { Role } from './roles' +import type { Permission } from './permissions' +import type { ApiCredential } from './api_credentials' + + +type OrganizationType = 'organizations' +type OrganizationRel = ResourceRel & { type: OrganizationType } + + +interface Organization extends Resource { + + readonly type: OrganizationType + + name: string + slug: string + domain: string + support_phone?: string | null + support_email?: string | null + logo_url?: string | null + favicon_url?: string | null + primary_color?: string | null + contrast_color?: string | null + gtm_id?: string | null + gtm_id_test?: string | null + discount_disabled?: boolean | null + account_disabled?: boolean | null + acceptance_disabled?: boolean | null + max_concurrent_promotions: number + max_concurrent_imports: number + region?: string | null + can_switch_live: boolean + subscription_totals: Record + + memberships?: Membership[] | null + roles?: Role[] | null + permissions?: Permission[] | null + api_credentials?: ApiCredential[] | null + +} + + +interface OrganizationCreate extends ResourceCreate { + + name: string + support_phone?: string | null + support_email?: string | null + logo_url?: string | null + favicon_url?: string | null + primary_color?: string | null + contrast_color?: string | null + gtm_id?: string | null + gtm_id_test?: string | null + discount_disabled?: boolean | null + account_disabled?: boolean | null + acceptance_disabled?: boolean | null + region?: string | null + +} + + +interface OrganizationUpdate extends ResourceUpdate { + + name?: string | null + support_phone?: string | null + support_email?: string | null + logo_url?: string | null + favicon_url?: string | null + primary_color?: string | null + contrast_color?: string | null + gtm_id?: string | null + gtm_id_test?: string | null + discount_disabled?: boolean | null + account_disabled?: boolean | null + acceptance_disabled?: boolean | null + +} + + +class Organizations extends ApiResource { + + static readonly TYPE: OrganizationType = 'organizations' as const + + async create(resource: OrganizationCreate, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + return this.resources.create({ ...resource, type: Organizations.TYPE }, params, options) + } + + async update(resource: OrganizationUpdate, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + return this.resources.update({ ...resource, type: Organizations.TYPE }, params, options) + } + + async transfer_ownership(organizationId: string | Organization, payload: TransferOwnershipDataType, options?: ResourcesConfig): Promise { + const _organizationId = (organizationId as Organization).id || organizationId as string + await this.resources.action('patch', `organizations/${_organizationId}/transfer_ownership`, { ...payload }, options) + } + + async memberships(organizationId: string | Organization, params?: QueryParamsList, options?: ResourcesConfig): Promise> { + const _organizationId = (organizationId as Organization).id || organizationId as string + return this.resources.fetch({ type: 'memberships' }, `organizations/${_organizationId}/memberships`, params, options) as unknown as ListResponse + } + + async roles(organizationId: string | Organization, params?: QueryParamsList, options?: ResourcesConfig): Promise> { + const _organizationId = (organizationId as Organization).id || organizationId as string + return this.resources.fetch({ type: 'roles' }, `organizations/${_organizationId}/roles`, params, options) as unknown as ListResponse + } + + async permissions(organizationId: string | Organization, params?: QueryParamsList, options?: ResourcesConfig): Promise> { + const _organizationId = (organizationId as Organization).id || organizationId as string + return this.resources.fetch({ type: 'permissions' }, `organizations/${_organizationId}/permissions`, params, options) as unknown as ListResponse + } + + async api_credentials(organizationId: string | Organization, params?: QueryParamsList, options?: ResourcesConfig): Promise> { + const _organizationId = (organizationId as Organization).id || organizationId as string + return this.resources.fetch({ type: 'api_credentials' }, `organizations/${_organizationId}/api_credentials`, params, options) as unknown as ListResponse + } + + + isOrganization(resource: any): resource is Organization { + return resource.type && (resource.type === Organizations.TYPE) + } + + + relationship(id: string | ResourceId | null): OrganizationRel { + return ((id === null) || (typeof id === 'string')) ? { id, type: Organizations.TYPE } : { id: id.id, type: Organizations.TYPE } + } + + + type(): OrganizationType { + return Organizations.TYPE + } + +} + + +export default Organizations + +export type { Organization, OrganizationCreate, OrganizationUpdate, OrganizationType } +export type TransferOwnershipDataType = { new_owner_email: string } diff --git a/src/resources/permissions.ts b/src/resources/permissions.ts new file mode 100644 index 0000000..48e9349 --- /dev/null +++ b/src/resources/permissions.ts @@ -0,0 +1,103 @@ +import { ApiResource } from '../resource' +import type { Resource, ResourceCreate, ResourceUpdate, ResourceId, ResourcesConfig, ResourceRel, ListResponse } from '../resource' +import type { QueryParamsRetrieve, QueryParamsList } from '../query' + +import type { Organization } from './organizations' +import type { Role, RoleType } from './roles' +import type { Version } from './versions' + + +type PermissionType = 'permissions' +type PermissionRel = ResourceRel & { type: PermissionType } +type RoleRel = ResourceRel & { type: RoleType } + + +interface Permission extends Resource { + + readonly type: PermissionType + + can_create: boolean + can_read: boolean + can_update: boolean + can_destroy: boolean + subject: string + restrictions: Record + + organization?: Organization | null + role?: Role | null + versions?: Version[] | null + +} + + +interface PermissionCreate extends ResourceCreate { + + can_create: boolean + can_read: boolean + can_update: boolean + can_destroy: boolean + subject: string + + role: RoleRel + +} + + +interface PermissionUpdate extends ResourceUpdate { + + can_create?: boolean | null + can_read?: boolean | null + can_update?: boolean | null + can_destroy?: boolean | null + +} + + +class Permissions extends ApiResource { + + static readonly TYPE: PermissionType = 'permissions' as const + + async create(resource: PermissionCreate, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + return this.resources.create({ ...resource, type: Permissions.TYPE }, params, options) + } + + async update(resource: PermissionUpdate, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + return this.resources.update({ ...resource, type: Permissions.TYPE }, params, options) + } + + async organization(permissionId: string | Permission, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + const _permissionId = (permissionId as Permission).id || permissionId as string + return this.resources.fetch({ type: 'organizations' }, `permissions/${_permissionId}/organization`, params, options) as unknown as Organization + } + + async role(permissionId: string | Permission, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + const _permissionId = (permissionId as Permission).id || permissionId as string + return this.resources.fetch({ type: 'roles' }, `permissions/${_permissionId}/role`, params, options) as unknown as Role + } + + async versions(permissionId: string | Permission, params?: QueryParamsList, options?: ResourcesConfig): Promise> { + const _permissionId = (permissionId as Permission).id || permissionId as string + return this.resources.fetch({ type: 'versions' }, `permissions/${_permissionId}/versions`, params, options) as unknown as ListResponse + } + + + isPermission(resource: any): resource is Permission { + return resource.type && (resource.type === Permissions.TYPE) + } + + + relationship(id: string | ResourceId | null): PermissionRel { + return ((id === null) || (typeof id === 'string')) ? { id, type: Permissions.TYPE } : { id: id.id, type: Permissions.TYPE } + } + + + type(): PermissionType { + return Permissions.TYPE + } + +} + + +export default Permissions + +export type { Permission, PermissionCreate, PermissionUpdate, PermissionType } diff --git a/src/resources/roles.ts b/src/resources/roles.ts new file mode 100644 index 0000000..a2f8652 --- /dev/null +++ b/src/resources/roles.ts @@ -0,0 +1,106 @@ +import { ApiResource } from '../resource' +import type { Resource, ResourceCreate, ResourceUpdate, ResourceId, ResourcesConfig, ResourceRel, ListResponse } from '../resource' +import type { QueryParamsRetrieve, QueryParamsList } from '../query' + +import type { Organization, OrganizationType } from './organizations' +import type { Permission } from './permissions' +import type { Membership } from './memberships' +import type { ApiCredential } from './api_credentials' +import type { Version } from './versions' + + +type RoleType = 'roles' +type RoleRel = ResourceRel & { type: RoleType } +type OrganizationRel = ResourceRel & { type: OrganizationType } + + +interface Role extends Resource { + + readonly type: RoleType + + name: string + kind: string + + organization?: Organization | null + permissions?: Permission[] | null + memberships?: Membership[] | null + api_credentials?: ApiCredential[] | null + versions?: Version[] | null + +} + + +interface RoleCreate extends ResourceCreate { + + name: string + + organization: OrganizationRel + +} + + +interface RoleUpdate extends ResourceUpdate { + + name?: string | null + +} + + +class Roles extends ApiResource { + + static readonly TYPE: RoleType = 'roles' as const + + async create(resource: RoleCreate, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + return this.resources.create({ ...resource, type: Roles.TYPE }, params, options) + } + + async update(resource: RoleUpdate, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + return this.resources.update({ ...resource, type: Roles.TYPE }, params, options) + } + + async organization(roleId: string | Role, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + const _roleId = (roleId as Role).id || roleId as string + return this.resources.fetch({ type: 'organizations' }, `roles/${_roleId}/organization`, params, options) as unknown as Organization + } + + async permissions(roleId: string | Role, params?: QueryParamsList, options?: ResourcesConfig): Promise> { + const _roleId = (roleId as Role).id || roleId as string + return this.resources.fetch({ type: 'permissions' }, `roles/${_roleId}/permissions`, params, options) as unknown as ListResponse + } + + async memberships(roleId: string | Role, params?: QueryParamsList, options?: ResourcesConfig): Promise> { + const _roleId = (roleId as Role).id || roleId as string + return this.resources.fetch({ type: 'memberships' }, `roles/${_roleId}/memberships`, params, options) as unknown as ListResponse + } + + async api_credentials(roleId: string | Role, params?: QueryParamsList, options?: ResourcesConfig): Promise> { + const _roleId = (roleId as Role).id || roleId as string + return this.resources.fetch({ type: 'api_credentials' }, `roles/${_roleId}/api_credentials`, params, options) as unknown as ListResponse + } + + async versions(roleId: string | Role, params?: QueryParamsList, options?: ResourcesConfig): Promise> { + const _roleId = (roleId as Role).id || roleId as string + return this.resources.fetch({ type: 'versions' }, `roles/${_roleId}/versions`, params, options) as unknown as ListResponse + } + + + isRole(resource: any): resource is Role { + return resource.type && (resource.type === Roles.TYPE) + } + + + relationship(id: string | ResourceId | null): RoleRel { + return ((id === null) || (typeof id === 'string')) ? { id, type: Roles.TYPE } : { id: id.id, type: Roles.TYPE } + } + + + type(): RoleType { + return Roles.TYPE + } + +} + + +export default Roles + +export type { Role, RoleCreate, RoleUpdate, RoleType } diff --git a/src/resources/user.ts b/src/resources/user.ts new file mode 100644 index 0000000..4a70a0c --- /dev/null +++ b/src/resources/user.ts @@ -0,0 +1,62 @@ +import { ApiSingleton } from '../resource' +import type { Resource, ResourceUpdate, ResourceId, ResourcesConfig, ResourceRel } from '../resource' +import type { QueryParamsRetrieve } from '../query' + + + +type UserType = 'user' +type UserRel = ResourceRel & { type: UserType } + + +interface User extends Resource { + + readonly type: UserType + + email: string + first_name: string + last_name: string + time_zone?: string | null + +} + + +interface UserUpdate extends ResourceUpdate { + + email?: string | null + first_name?: string | null + last_name?: string | null + time_zone?: string | null + +} + + +class Users extends ApiSingleton { + + static readonly TYPE: UserType = 'user' as const + + async update(resource: UserUpdate, params?: QueryParamsRetrieve, options?: ResourcesConfig): Promise { + const res = await this.retrieve(params, options) // JsonAPI requires id in the request body + return this.resources.update({ ...resource, id: res.id, type: Users.TYPE }, params, options) + } + + + isUser(resource: any): resource is User { + return resource.type && (resource.type === Users.TYPE) + } + + + relationship(id: string | ResourceId | null): UserRel { + return ((id === null) || (typeof id === 'string')) ? { id, type: Users.TYPE } : { id: id.id, type: Users.TYPE } + } + + + type(): UserType { + return Users.TYPE + } + +} + + +export default Users + +export type { User, UserUpdate, UserType } diff --git a/src/resources/versions.ts b/src/resources/versions.ts new file mode 100644 index 0000000..e343af2 --- /dev/null +++ b/src/resources/versions.ts @@ -0,0 +1,50 @@ +import { ApiResource } from '../resource' +import type { Resource, ResourceId, ResourceRel } from '../resource' + + + + +type VersionType = 'versions' +type VersionRel = ResourceRel & { type: VersionType } + + +interface Version extends Resource { + + readonly type: VersionType + + resource_type: string + resource_id: string + event: string + changes: Record + who: Record + +} + + +class Versions extends ApiResource { + + static readonly TYPE: VersionType = 'versions' as const + + + + + isVersion(resource: any): resource is Version { + return resource.type && (resource.type === Versions.TYPE) + } + + + relationship(id: string | ResourceId | null): VersionRel { + return ((id === null) || (typeof id === 'string')) ? { id, type: Versions.TYPE } : { id: id.id, type: Versions.TYPE } + } + + + type(): VersionType { + return Versions.TYPE + } + +} + + +export default Versions + +export type { Version, VersionType } diff --git a/src/static.ts b/src/static.ts new file mode 100644 index 0000000..4debfab --- /dev/null +++ b/src/static.ts @@ -0,0 +1,37 @@ + +import * as api from './api' +import { SdkError, ApiError} from './error' +import CommerceLayerProvisioning, { OPEN_API_SCHEMA_VERSION } from './commercelayer' +import type { CommerceLayerProvisioningClient, CommerceLayerInitConfig } from './commercelayer' + + +/* Static functions */ +export const CommerceLayerProvisioningStatic = { + + resources: (sort?: boolean): readonly string[] => { + return sort? [ ...api.resourceList ].sort() : api.resourceList + }, + + singletons: (sort?: boolean): readonly string[] => { + return sort? [ ...api.singletonList ].sort() : api.singletonList + }, + + isSingleton: (resource: api.ResourceTypeLock): boolean => { + return (api.singletonList as unknown as api.ResourceTypeLock[]).includes(resource) + }, + + isSdkError: (error: unknown): error is SdkError => { + return SdkError.isSdkError(error) + }, + + isApiError: (error: unknown): error is ApiError => { + return ApiError.isApiError(error) + }, + + init: (config: CommerceLayerInitConfig): CommerceLayerProvisioningClient => { + return CommerceLayerProvisioning(config) + }, + + get schemaVersion(): string { return OPEN_API_SCHEMA_VERSION } + +} diff --git a/src/util.ts b/src/util.ts new file mode 100644 index 0000000..d6a0553 --- /dev/null +++ b/src/util.ts @@ -0,0 +1,47 @@ +import type { ObjectType } from "../src/common" +// import path from 'path' + + + +const sleep = async (ms: number): Promise => { + return new Promise(resolve => setTimeout(resolve, ms)) +} + + +const sortObjectFields = (obj: ObjectType): ObjectType => { + const sorted = Object.keys(obj).sort().reduce((accumulator: ObjectType, key: string) => { + accumulator[key] = obj[key]; + return accumulator; + }, {}) + return sorted +} + +/* +const nestedField = (obj: any, field: string): { key: string, val: any } => { + + let fp = field + if (fp.endsWith('.')) fp = fp.substring(0, fp.length-1) + + const dots = field.split(".") + + const key = dots[dots.length-1] + let val = obj + while (dots.length && (val = val[dots.shift() || ''])); + + return { key, val } +} +*/ + +/* +const packageInfo = (fields?: string | string[], options?: any): Record => { + const pjson = require(path.resolve('./', 'package.json')) + return fields? (Array.isArray(fields)? fields : [ fields ]).reduce((info: any, field) => { + const nf = nestedField(pjson, field) + info[options?.nestedName? nf.key : field] = nf.val + return info + }, {}) : pjson +} +*/ + + +export { sleep, sortObjectFields, /* packageInfo */ } diff --git a/test/common.ts b/test/common.ts new file mode 100644 index 0000000..e584178 --- /dev/null +++ b/test/common.ts @@ -0,0 +1,182 @@ +import getToken from './token' +import CommerceLayer, { CommerceLayerProvisioningClient, QueryParamsList, QueryParamsRetrieve } from '../src' +import dotenv from 'dotenv' +import { inspect } from 'util' +import axios, { AxiosRequestConfig } from 'axios' +import { isEqual } from 'lodash' +import { RequestConfig } from '../src/client' + +dotenv.config() + +const GLOBAL_TIMEOUT = 15000 + +const domain = process.env.CL_SDK_DOMAIN as string + +export { domain } + +const INTERCEPTOR_CANCEL = 'TEST-INTERCEPTED' +const REQUEST_TIMEOUT = 5550 +const REQUEST_OPTIONS: RequestConfig = { + timeout: REQUEST_TIMEOUT, + params: { } +} as const + +export const TestData = { + id: 'testId', + reference: 'sdk-test', + reference_origin: 'cl-sdk', + metadata: { + meta_key_1: 'meta_value_1', + } +} as const + + +const COMMON_PARAMS_FILTERS = { reference_eq: TestData.reference } + +const COMMON_PARAMS_LIST: QueryParamsList = { + filters: COMMON_PARAMS_FILTERS, + pageSize: 25, + pageNumber: 1, + sort: { updated_at: 'desc', created_at: 'asc', reference: 'desc' }, +} as const + +const COMMON_PARAMS_FIELDS = ['id', 'reference', 'reference_origin', 'updated_at', 'metadata'] +const COMMON_PARAMS_RETRIEVE = { + fields: COMMON_PARAMS_FIELDS, +} + + +export const CommonData = { + options: REQUEST_OPTIONS, + paramsRetrieve: COMMON_PARAMS_RETRIEVE, + paramsList: COMMON_PARAMS_LIST, + paramsFields: COMMON_PARAMS_FIELDS, +} as const + + +let currentAccessToken: string + +const initClient = async (): Promise => { + const token = await getToken('user') + if (token === null) throw new Error('Unable to get access token') + const accessToken = token.accessToken + currentAccessToken = accessToken + const client = CommerceLayer({ accessToken, domain }) + client.config({ timeout: GLOBAL_TIMEOUT }) + jest.setTimeout(GLOBAL_TIMEOUT) + return client +} + +const fakeClient = async (): Promise => { + const accessToken = 'fake-access-token' + const client = CommerceLayer({ accessToken, domain }) + currentAccessToken = accessToken + return client +} + +const getClient = (instance?: boolean): Promise => { + return instance ? initClient() : fakeClient() +} + +const printObject = (obj: unknown): string => { + return inspect(obj, false, null, true) +} + + +export { initClient, fakeClient, getClient, printObject, currentAccessToken } + + + +const handleError = (error: any) => { + if (error.message !== INTERCEPTOR_CANCEL) throw error +} + +const interceptRequest = (config?: AxiosRequestConfig): AxiosRequestConfig => { + if (!config) throw new axios.Cancel(INTERCEPTOR_CANCEL) + return config +} + +const randomValue = (type: string, name?: string): any | Array => { + + const numbers = [0, 1, 10, 100, 1000, 10000, 5, 55, 555, 12345, 6666] + const strings = ['alfa', 'beta', 'gamma', 'delta', 'epsilon', 'kappa', 'lambda', 'omega', 'sigma', 'zeta'] + const booleans = [true, false, true, false, true, false, true, false, true, false] + const objects = [{ key11: 'val11' }, { key21: 'val21' }, { key31: 'val31' }, { key41: 'val41' }, { key51: 'val51' }] + + let values: Array + + if (name) { + // type = + } + + if (type.startsWith('boolean')) values = booleans + else + if (type.startsWith('integer') || type.startsWith('number')) values = numbers + else + if (type.startsWith('fload') || type.startsWith('decimal')) values = numbers + else + if (type.startsWith('object')) values = objects + else + if (type.startsWith('string')) values = strings + else values = strings + + let value = values[Math.floor(Math.random() * (values.length - 1))] + + if (type === 'string') value = `${value}_${Math.floor(Math.random() * 100)}` + + if (type.endsWith('[]')) value = [ value ] + + return value + +} + + +export { handleError, interceptRequest, randomValue } + + + +const checkCommon = (config: AxiosRequestConfig, type: string, id?: string, token?: string, relationship?: string) => { + expect(config.url).toBe(type + (id ? `/${id}` : '') + (relationship ? `/${relationship}`: '')) + expect(config.headers?.Authorization).toContain('Bearer ' + (token || '')) + expect(config.timeout).toBe(REQUEST_TIMEOUT) +} + +const checkCommonData = (config: AxiosRequestConfig, type: string, attributes: any, id?: string) => { + if (id) expect(config.data.data.id).toBe(id) + expect(config.data.data.type).toBe(type) + const relationships: { [k: string]: any } = {} + Object.entries(config.data.data.relationships).forEach(([k, v]) => relationships[k] = (v as any)['data']) + const received = { + ...config.data.data.attributes, + ...relationships + } + expect(isEqual(received, attributes)).toBeTruthy() +} + +const checkParam = (params: any, name: string, value: string | number | boolean) => { + expect(params).toHaveProperty([name]) + expect(params[name]).toBe(String(value)) +} + +const checkCommonParamsList = (config: AxiosRequestConfig, params: QueryParamsList) => { + if (params.pageNumber) checkParam(config.params, 'page[number]', params.pageNumber) + if (params.pageSize) checkParam(config.params, 'page[size]', params.pageSize) + if (params.filters?.reference_eq) checkParam(config.params, 'filter[q][reference_eq]', params.filters.reference_eq) + if (params.sort) { + let value: string + if (Array.isArray(params.sort)) value = params.sort.join(',') + else value = Object.entries(params.sort).map(([k, v]) => `${(v === 'desc') ? '-' : ''}${k}`).join(',') + checkParam(config.params, 'sort', value) + } +} + +const checkCommonParams = (config: AxiosRequestConfig, params: QueryParamsRetrieve) => { + if (params.fields) { + Object.entries(params.fields).forEach(([type, fields]) => { + checkParam(config.params, `fields[${type}]`, fields.join(',')) + }) + } +} + + +export { checkCommon, checkCommonData, checkCommonParams, checkCommonParamsList } diff --git a/test/interceptor.ts b/test/interceptor.ts new file mode 100644 index 0000000..d2ff0cf --- /dev/null +++ b/test/interceptor.ts @@ -0,0 +1,49 @@ + +import clProvisioning, { ErrorObj, RequestObj, ResponseObj } from '../src' +import getToken from './token' + + +const requestInterceptor = (request: RequestObj): RequestObj => { + console.log('INSIDE REQUEST INTERCEPTOR') + // console.log(request) + return request +} + +const responseInterceptor = (response: ResponseObj): ResponseObj => { + console.log('INSIDE RESPONSE INTERCEPTOR') + console.log(response) + return response +} + +const errorInterceptor = (error: ErrorObj): ErrorObj => { + console.log('INSIDE RESPONSE INTERCEPTOR') + console.log(error) + return error +} + + + +(async () => { + + const organization = process.env.CL_SDK_ORGANIZATION || '' + const auth = await getToken('user') + const accessToken = auth? auth.accessToken+'x' : '' + + const cl = clProvisioning({ + accessToken, + timeout: 5000, + }) + + const rrr = cl.addRawResponseReader({ headers: true }) + const reqInt = cl.addRequestInterceptor(requestInterceptor) + cl.addResponseInterceptor(responseInterceptor, errorInterceptor) + + const organizations = await cl.organizations.list({ pageSize: 1 }).catch(error => console.log(error.message)) + + cl.removeInterceptor('request', reqInt) + + console.log(organizations) + console.log(rrr.rawResponse) + console.log(rrr.headers) + +})() diff --git a/test/spot.ts b/test/spot.ts new file mode 100644 index 0000000..660f7c5 --- /dev/null +++ b/test/spot.ts @@ -0,0 +1,27 @@ + +import clProvisioning from '../src' +import { inspect } from 'util' +import getToken from './token' + + +(async () => { + + const auth = await getToken('user') + const accessToken = auth ? auth.accessToken : '' + + const clp = clProvisioning({ + accessToken, + timeout: 5000, + }) + + try { + + clp.memberships.resend('id') + clp.organizations.transfer_ownership('id', { new_owner_email: '' }) + + } catch (error: any) { + console.log(inspect(error, false, null, true)) + console.log(error.message) + } + +})() diff --git a/test/token.ts b/test/token.ts new file mode 100644 index 0000000..ec17555 --- /dev/null +++ b/test/token.ts @@ -0,0 +1,56 @@ +import { provisioning } from '@commercelayer/js-auth' +import dotenv from 'dotenv' + +dotenv.config() + + +type TokenType = 'user' + +export type AuthScope = string | string[] + +type AuthData = { + clientId: string + clientSecret?: string + domain?: string +} + + +export type AccessToken = { + accessToken: string; + tokenType: 'bearer' | 'Bearer'; + expiresIn: number; + expires: Date; + scope: AuthScope; + createdAt: number; + error?: string; + errorDescription?: string; + } + + +const domain = process.env.CL_SDK_DOMAIN +const clientId = process.env.CL_SDK_CLIENT_ID || '' +const clientSecret = process.env.CL_SDK_CLIENT_SECRET || '' + + +export default async (type: TokenType): Promise => { + switch (type) { + case 'user': + default: return getAccessToken({ clientId, clientSecret, domain }) + } +} + + + + + +const getAccessToken = async (auth: AuthData): Promise => { + + const credentials: any = { + clientId: auth.clientId, + clientSecret: auth.clientSecret, + domain: auth.domain + } + + return provisioning.authentication(credentials) + + } diff --git a/tsconfig.esm.json b/tsconfig.esm.json new file mode 100644 index 0000000..1199ef3 --- /dev/null +++ b/tsconfig.esm.json @@ -0,0 +1,72 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + "incremental": true /* Enable incremental compilation */, + "target": "ES2018" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, + "module": "ES6" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + // "lib": [], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ + "declaration": true /* Generates corresponding '.d.ts' file. */, + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "lib/esm" /* Redirect output structure to the directory. */, + "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ + + /* Module Resolution Options */ + "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + }, + "include": ["src/**/*"] +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..0db07fc --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,72 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig.json to read more about this file */ + + /* Basic Options */ + "incremental": true /* Enable incremental compilation */, + "target": "ES2018" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, + "module": "commonjs" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, + // "lib": [], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */ + "declaration": true /* Generates corresponding '.d.ts' file. */, + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + // "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "lib/cjs" /* Redirect output structure to the directory. */, + "rootDir": "./src" /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */, + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + + /* Strict Type-Checking Options */ + "strict": true /* Enable all strict type-checking options. */, + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + // "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */ + // "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */ + + /* Module Resolution Options */ + "moduleResolution": "node" /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */, + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */, + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + + /* Experimental Options */ + // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ + + /* Advanced Options */ + "skipLibCheck": true /* Skip type checking of declaration files. */, + "forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */ + }, + "include": ["src/**/*"] +}