diff --git a/.babelrc b/.babelrc index e1f3fc1..081c354 100644 --- a/.babelrc +++ b/.babelrc @@ -1,5 +1,8 @@ { - "plugins": ["@babel/plugin-proposal-class-properties"], + "plugins": [ + ["@babel/plugin-transform-class-properties", { "loose": true }], + "@babel/plugin-transform-optional-chaining" +], "presets": [ "@babel/preset-typescript", [ diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml new file mode 100644 index 0000000..f042fd1 --- /dev/null +++ b/.github/workflows/ci.yml @@ -0,0 +1,40 @@ +name: CI + +on: + push: + branches: + - master + pull_request: + branches: + - master + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + build-and-test: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + - name: Use Node.js 20.x + uses: actions/setup-node@v4 + with: + node-version: 20.x + - name: Build SDK + run: | + npm install + npm run build + - name: Install test-app dependencies + run: npm install + working-directory: test-app + - name: Install Playwright browsers + run: npx playwright install --with-deps chromium + working-directory: test-app + - name: Run Playwright tests + run: npx playwright test + working-directory: test-app + env: + CI: true diff --git a/.github/workflows/nodejs.yml b/.github/workflows/nodejs.yml deleted file mode 100644 index b328240..0000000 --- a/.github/workflows/nodejs.yml +++ /dev/null @@ -1,31 +0,0 @@ -name: Node CI - -on: - push: - pull_request: - branches: - - master - -jobs: - build: - - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [12.x] - - steps: - - uses: actions/checkout@v1 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - name: Build and Test - run: | - npm install - npm run build - npm run test - npm run report-coverage - env: - CI: true diff --git a/.github/workflows/npmpublish.yml b/.github/workflows/npmpublish.yml deleted file mode 100644 index 0159c40..0000000 --- a/.github/workflows/npmpublish.yml +++ /dev/null @@ -1,48 +0,0 @@ -name: Publish - -on: - release: - types: [published] - - -jobs: - build: - - runs-on: ubuntu-latest - - strategy: - matrix: - node-version: [12.x] - - steps: - - uses: actions/checkout@v1 - - name: Use Node.js ${{ matrix.node-version }} - uses: actions/setup-node@v1 - with: - node-version: ${{ matrix.node-version }} - - name: Build and Test - run: | - npm install - npm run build - npm run test - env: - CI: true - - publish: - needs: build - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v1 - - uses: actions/setup-node@v1 - with: - node-version: 12 - registry-url: https://registry.npmjs.org/ - - name: NPM Publish - run: | - npm install - npm run build - npm config set //registry.npmjs.org/:_authToken=$NODE_AUTH_TOKEN - npm publish - env: - NODE_AUTH_TOKEN: ${{secrets.npm_token}} - CI: true \ No newline at end of file diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml new file mode 100644 index 0000000..68c47d7 --- /dev/null +++ b/.github/workflows/publish-npm.yml @@ -0,0 +1,38 @@ +name: Publish + +on: + release: + types: [published] + + +jobs: + publish: + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - uses: actions/checkout@v4 + - name: Use Node.js 20.x + uses: actions/setup-node@v4 + with: + node-version: 20.x + registry-url: https://registry.npmjs.org/ + - name: NPM Publish + run: | + npm install + npm run build + # print the NPM user name for validation + npm whoami + VERSION=$(node -p "require('./package.json').version" ) + # Only publish stable versions to the latest tag + if [[ "$VERSION" =~ ^[^-]+$ ]]; then + NPM_TAG="latest" + else + NPM_TAG="beta" + fi + echo "Publishing $VERSION with $NPM_TAG tag." + npm publish --tag $NPM_TAG --provenance --access public + env: + NODE_AUTH_TOKEN: ${{secrets.npm_token}} + CI: true \ No newline at end of file diff --git a/.github/workflows/release-please.yml b/.github/workflows/release-please.yml new file mode 100644 index 0000000..b5c447e --- /dev/null +++ b/.github/workflows/release-please.yml @@ -0,0 +1,20 @@ +name: Release Please +on: + push: + branches: + - master + +permissions: + contents: write + pull-requests: write + +jobs: + release-please: + if: github.repository == 'imagekit-developer/imagekit-javascript' + runs-on: ubuntu-latest + + steps: + - uses: googleapis/release-please-action@5c625bfb5d1ff62eadeeb3772007f7f66fdcf071 # v4.4.1 + id: release + with: + token: ${{ secrets.RELEASE_PLEASE_TOKEN }} diff --git a/.github/workflows/sync-release-as.yml b/.github/workflows/sync-release-as.yml new file mode 100644 index 0000000..9915004 --- /dev/null +++ b/.github/workflows/sync-release-as.yml @@ -0,0 +1,63 @@ +name: Sync Release-As from release PR title + +on: + pull_request: + types: [edited] + +permissions: + contents: write + +jobs: + sync: + if: >- + github.event.pull_request.base.ref == 'master' && + startsWith(github.event.pull_request.head.ref, 'release-please--') && + github.event.changes.title != null + runs-on: ubuntu-latest + steps: + - name: Extract versions from old and new title + id: parse + env: + NEW_TITLE: ${{ github.event.pull_request.title }} + OLD_TITLE: ${{ github.event.changes.title.from }} + run: | + # Anchored on pull-request-title-pattern "release: ${version}" from release-please-config.json. + extract() { + echo "$1" | grep -oE '^release:[[:space:]]+v?[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.-]+)?' \ + | sed -E 's/^release:[[:space:]]+v?//' + } + NEW_VERSION=$(extract "$NEW_TITLE") + OLD_VERSION=$(extract "$OLD_TITLE") + echo "old=$OLD_VERSION" + echo "new=$NEW_VERSION" + if [ -z "$NEW_VERSION" ]; then + echo "::notice::No semver in new title; nothing to do." + echo "skip=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + if [ "$NEW_VERSION" = "$OLD_VERSION" ]; then + echo "::notice::Version unchanged ($NEW_VERSION); not pushing." + echo "skip=true" >> "$GITHUB_OUTPUT" + exit 0 + fi + echo "version=$NEW_VERSION" >> "$GITHUB_OUTPUT" + + - name: Check out master + if: steps.parse.outputs.skip != 'true' + uses: actions/checkout@v6 + with: + ref: master + token: ${{ secrets.RELEASE_PLEASE_TOKEN }} + fetch-depth: 1 + + - name: Push empty Release-As commit + if: steps.parse.outputs.skip != 'true' + env: + VERSION: ${{ steps.parse.outputs.version }} + run: | + git config user.name "release-as-bot" + git config user.email "release-as-bot@users.noreply.github.com" + git commit --allow-empty -m "chore: pin next release + + Release-As: ${VERSION}" + git push origin master diff --git a/.gitignore b/.gitignore index 48d5826..736009f 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,4 @@ -node_modules/* -samples/sample-app/node_modules/* +node_modules .env .vscode .DS_Store @@ -7,4 +6,5 @@ dist .nyc_output coverage.lcov coverage -out-tsc \ No newline at end of file +out-tsc +docs \ No newline at end of file diff --git a/.mocharc.json b/.mocharc.json deleted file mode 100644 index b758d0a..0000000 --- a/.mocharc.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "coverage": true, - "require": ["esm", "./babel-register.js"], - "exit": true, - "timeout": "40000" -} \ No newline at end of file diff --git a/.npmignore b/.npmignore new file mode 100644 index 0000000..483a9c4 --- /dev/null +++ b/.npmignore @@ -0,0 +1 @@ +package-lock.json \ No newline at end of file diff --git a/.nycrc.json b/.nycrc.json deleted file mode 100644 index 55fa7d5..0000000 --- a/.nycrc.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "reporter": ["lcov", "text"], - "exclude": ["babel-register.js", "test"], - "include": ["src"] -} \ No newline at end of file diff --git a/.release-please-manifest.json b/.release-please-manifest.json new file mode 100644 index 0000000..9b4851f --- /dev/null +++ b/.release-please-manifest.json @@ -0,0 +1,3 @@ +{ + ".": "5.4.1" +} diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..7e48c4c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,141 @@ +# Changelog + +## [5.4.1](https://github.com/imagekit-developer/imagekit-javascript/compare/5.4.0...v5.4.1) (2026-06-01) + + +### Bug Fixes + +* **ci:** use fine-grained PAT for creating PR ([d32b6ed](https://github.com/imagekit-developer/imagekit-javascript/commit/d32b6ed379b561636f612e6fe7db051460c99ea4)) +* make safeBtoa browser-safe with UTF-8 handling ([cca89cf](https://github.com/imagekit-developer/imagekit-javascript/commit/cca89cfe9961606f871f1de23091f2e2a56c8370)) +* **transformation:** improve safeBtoa for UTF-8 handling and add tests for Hindi characters ([1343333](https://github.com/imagekit-developer/imagekit-javascript/commit/134333325952329925a7711031ea9d9aa8f5ac4d)) + + +### Chores + +* add release automation workflows and configuration files ([efabbab](https://github.com/imagekit-developer/imagekit-javascript/commit/efabbab2b2e0d3852ee42f9431c7abdbfe913785)) +* **deps:** remove unused babel and rollup plugins from devDependencies ([774bedf](https://github.com/imagekit-developer/imagekit-javascript/commit/774bedf3ad2569301994eb87a40d226720b47f5a)) +* remove unused code blocks from the repository ([82a556b](https://github.com/imagekit-developer/imagekit-javascript/commit/82a556beabfb002701cc2b6a79f7fa7a03fb121c)) + +## Changelog + +## Version 5.4.0 + +1. **Enhancement:** + - Added support for new crop modes: `maintain_ratio_no_enlarge`, `pad_resize_no_enlarge` and `pad_extract_no_shrink` + - Added support for `colorize` transformation + +## Version 5.3.0 + +1. **Enhancement:** + - Added support for new overlay position parameters: `xCenter` (`lxc`), `yCenter` (`lyc`), and `anchorPoint` (`lap`) in overlay transformations + +## Version 5.2.2 + +1. Updated TypeScript types to allow string values for the `dpr` parameter in transformations, enabling support for arithmetic expressions and dynamic DPR values. + +## Version 5.2.1 + +1. **Bug fix:** + - Updated subtitle overlay transformation parameter from `l-subtitle` to `l-subtitles` to align with API specification + +## Version 5.2.0 + +1. **New transformation parameters added:** + - `layerMode` (`lm`): Control layer blending modes in overlay transformations + - `aiEdit` (`e-edit`): AI-powered image editing transformation + - `colorReplace` (`cr`): Replace specific colors in images + - `distort` (`e-distort`): Apply distortion effects to images + +2. **Type definitions updated:** + - Improved TypeScript types by synchronizing with the official Node.js SDK + - Enhanced type safety for transformation options, upload options, and responses + +3. **Documentation improvements:** + - Added TypeScript versioning policy section to README + - Clarified how type definition improvements may be released in minor/patch versions + +_No runtime breaking changes from 5.1.x._ + +## Version 5.1.0 + +1. **New helper** `getResponsiveImageAttributes()` + Generates ready‑to‑use `src`, `srcSet`, and `sizes` for responsive `` tags (breakpoint pruning, DPR 1×/2×, custom breakpoints, no up‑scaling). +2. Added exports: + `getResponsiveImageAttributes`, `GetImageAttributesOptions`, `ResponsiveImageAttributes`. + +_No breaking changes from 5.0.x._ + +## Version 5.0.0 + +This version introduces major breaking changes, for usage examples, refer to the [official documentation](https://imagekit.io/docs/integration/javascript). + +1. The package has been renamed from `imagekit-javascript` to `@imagekit/javascript`. + Please update your dependency references and import statements accordingly. + +2. The default-exported `ImageKit` class has been removed and replaced with named exports: + - `buildSrc` + - `buildTransformationString` + - `upload` + - Error classes: `ImageKitInvalidRequestError`, `ImageKitAbortError`, `ImageKitUploadNetworkError`, `ImageKitServerError` + + Update your imports to use these named exports. + +3. The `upload` method supports `AbortSignal` for canceling uploads. + Upload error handling has been revamped, and `onProgress` callbacks are now supported. + Only the Promise-based syntax is supported. Callback style usage has been removed. + +4. Several internal interfaces (e.g., `ImageKitOptions`, `IKResponse`) have been updated or removed. + The upload options now require a `publicKey`, and a new `SrcOptions` interface has been introduced. + +--- + +## Version 4.0.1 + +### Bug Fixes + +1. Fixed overlay position x,y issue. + +--- + +## Version 4.0.0 + +### Breaking Changes + +1. The default value for `transformationPosition` is now `query` instead of `path`. This change enables wildcard cache purging to remove CDN cache for all generated transformations. + + **Action Required:** + If you're using the `transformationPosition` parameter in the `url` method and want to apply transformations in the path, you must now explicitly set the value to `path`. The default is `query`. + +2. Removed the following deprecated parameters: + `effectSharpen`, `effectUSM`, `effectContrast`, `effectGray`, `effectShadow`, `effectGradient`, and `rotate`. + +### Other Changes + +1. Native support for overlays has been added. See the README for usage examples. +2. New AI-powered transformations are now supported: + `aiRemoveBackground`, `aiUpscale`, `aiVariation`, `aiDropShadow`, `aiChangeBackground`, and more. + *(Introduced in version 3.1.0)* + +--- + +## SDK Version 3.0.0 + +### Breaking Changes + +- **Overlay Syntax Update** + In version 3.0.0, the old overlay syntax parameters for transformations (e.g., `oi`, `ot`, `obg`, and others as detailed [here](https://imagekit.io/docs/add-overlays-on-images)) have been removed. These parameters are deprecated and will now return errors when used in URLs. + + **Action Required:** + Migrate to the new layers syntax which supports overlay nesting, offers improved positional control, and allows more transformations at the layer level. For a quick start, refer to the [examples](https://imagekit.io/docs/add-overlays-on-images). Use the `raw` transformation parameter to implement this migration. + +--- + +## SDK Version 2.0.0 + +### Breaking Changes + +- **Authentication Process Update** + Previously, client-side file uploads required the SDK to be initialized with both the `publicKey` and `authenticationEndpoint` to fetch security parameters (`signature`, `token`, and `expire`). + + **Action Required:** + With version 2.0.0, you must now generate the security parameters (`signature`, `token`, and `expire`) yourself, eliminating the need for the `authenticationEndpoint`. When invoking the SDK's upload method, be sure to include these parameters along with other [upload options](https://imagekit.io/docs/api-reference/upload-file/upload-file#Request). For further details, consult the documentation [here](https://imagekit.io/docs/api-reference/upload-file/upload-file#how-to-implement-client-side-file-upload). diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..2027861 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 Image Kit + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index ebe0205..ccdd5bb 100644 --- a/README.md +++ b/README.md @@ -1,410 +1,46 @@ [ImageKit.io](https://imagekit.io) -# ImageKit.io Javascript SDK +# ImageKit.io JavaScript SDK -![gzip size](https://img.badgesize.io/https://unpkg.com/imagekit-javascript/dist/imagekit.min.js?compression=gzip&label=gzip) -![brotli size](https://img.badgesize.io/https://unpkg.com/imagekit-javascript/dist/imagekit.min.js?compression=brotli&label=brotli) -![Node CI](https://github.com/imagekit-developer/imagekit-javascript/workflows/Node%20CI/badge.svg) -[![npm version](https://img.shields.io/npm/v/imagekit-javascript)](https://www.npmjs.com/package/imagekit-javascript) -[![codecov](https://codecov.io/gh/imagekit-developer/imagekit-javascript/branch/master/graph/badge.svg)](https://codecov.io/gh/imagekit-developer/imagekit-javascript) -[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) +![CI](https://github.com/imagekit-developer/imagekit-javascript/workflows/CI/badge.svg) +[![npm version](https://img.shields.io/npm/v/@imagekit/javascript)](https://www.npmjs.com/package/@imagekit/javascript) +[![License: Apache 2.0](https://img.shields.io/badge/License-Apache_2.0-blue.svg)](https://opensource.org/licenses/Apache-2.0) [![Twitter Follow](https://img.shields.io/twitter/follow/imagekitio?label=Follow&style=social)](https://twitter.com/ImagekitIo) -Javascript SDK for [ImageKit](https://imagekit.io/) provides URL generation for image & video resizing and provides an interface for file upload. This SDK is lightweight and has no dependency. You can also use this as an ES module. +This lightweight, dependency-free JavaScript SDK is designed specifically for browser use. It provides utility functions to generate image and video `src` URLs using [ImageKit transformations](https://imagekit.io/docs/transformations) and to upload files to the ImageKit media library. -ImageKit is complete media storage, optimization, and transformation solution that comes with an [image and video CDN](https://imagekit.io/features/imagekit-infrastructure). It can be integrated with your existing infrastructure - storage like AWS S3, web servers, your CDN, and custom domain names, allowing you to deliver optimized images in minutes with minimal code changes. +For server-side applications with Node.js, please refer to our official [Node.js SDK](https://github.com/imagekit-developer/imagekit-nodejs). ## Installation -### Using npm -Install `imagekit-javascript` -``` -npm install imagekit-javascript --save -#or -yarn add imagekit-javascript -``` - -Now import ImageKit -```js -import ImageKit from "imagekit-javascript" - -// or -const ImageKit = require("imagekit-javascript") -``` - -### Using CDN -You can download a specific version of this SDK from a global CDN. -``` -https://unpkg.com/imagekit-javascript@1.3.0/dist/imagekit.min.js -``` - -For the latest version, remove the version number i.e. -``` -https://unpkg.com/imagekit-javascript/dist/imagekit.min.js -``` - -Now load it using a ` -``` - -## Initialization - -`urlEndpoint` is required to use the SDK. You can get URL-endpoint from your ImageKit dashboard - https://imagekit.io/dashboard#url-endpoints - -``` -var imagekit = new ImageKit({ - urlEndpoint: "https://ik.imagekit.io/your_imagekit_id" -}); -``` - -`publicKey` and `authenticationEndpoint` parameters are required if you want to use the SDK for client-side file upload. You can get these parameters from the developer section in your ImageKit dashboard - https://imagekit.io/dashboard#developers -``` -var imagekit = new ImageKit({ - publicKey: "your_public_api_key", - urlEndpoint: "https://ik.imagekit.io/your_imagekit_id", - authenticationEndpoint: "http://www.yourserver.com/auth", -}); -``` - -*Note: Do not include your Private Key in any client-side code, including this SDK or its initialization. If you pass the `privateKey` parameter while initializing this SDK, it throws an error* - -## Demo Application - -The fastest way to get started is by running the demo application in [samples/sample-app](https://github.com/imagekit-developer/imagekit-javascript/tree/master/samples/sample-app) folder. Follow these steps to run the application locally: - -``` -git clone https://github.com/imagekit-developer/imagekit-javascript.git - -cd imagekit-javascript -``` - -Create a file `.env` using `sample.env` in the directory `samples/sample-app` and fill in your `PRIVATE_KEY`, `PUBLIC_KEY` and `URL_ENDPOINT` from your [imageKit dashboard](https://imagekit.io/dashboard#developers). `SERVER_PORT` must also be included as per the `sample.env` file. - -Now start the sample application by running: - -``` -// Run it from project root -yarn startSampleApp -``` - -## Usage -You can use this SDK for URL generation and client-side file uploads. - -### URL Generation - -**1. Using image path and image hostname or endpoint** - -This method allows you to create an URL to access a file using the relative file path and the ImageKit URL endpoint (`urlEndpoint`). The file can be an image, video, or any other static file supported by ImageKit. - -``` -var imageURL = imagekit.url({ - path: "/default-image.jpg", - urlEndpoint: "https://ik.imagekit.io/your_imagekit_id/endpoint/", - transformation: [{ - "height": "300", - "width": "400" - }] -}); -``` - -This results in a URL like +You can install the SDK in your project using npm or yarn. -``` -https://ik.imagekit.io/your_imagekit_id/endpoint/tr:h-300,w-400/default-image.jpg -``` - -**2. Using full image URL** - -This method allows you to add transformation parameters to an absolute URL. For example, if you have configured a custom CNAME and have absolute asset URLs in your database or CMS, you will often need this. - - -``` -var imageURL = imagekit.url({ - src: "https://ik.imagekit.io/your_imagekit_id/endpoint/default-image.jpg", - transformation: [{ - "height": "300", - "width": "400" - }] -}); -``` - -This results in a URL like - -``` -https://ik.imagekit.io/your_imagekit_id/endpoint/default-image.jpg?tr=h-300%2Cw-400 +```bash +npm install @imagekit/javascript ``` +## Documentation -The `.url()` method accepts the following parameters +Refer to the ImageKit [official documentation](https://imagekit.io/docs/integration/javascript) for more details on how to use the SDK. -| Option | Description | -| :----------------| :----------------------------- | -| urlEndpoint | Optional. The base URL to be appended before the path of the image. If not specified, the URL Endpoint specified at the time of SDK initialization is used. For example, https://ik.imagekit.io/your_imagekit_id/endpoint/ | -| path | Conditional. This is the path at which the image exists. For example, `/path/to/image.jpg`. Either the `path` or `src` parameter needs to be specified for URL generation. | -| src | Conditional. This is the complete URL of an image already mapped to ImageKit. For example, `https://ik.imagekit.io/your_imagekit_id/endpoint/path/to/image.jpg`. Either the `path` or `src` parameter needs to be specified for URL generation. | -| transformation | Optional. An array of objects specifying the transformation to be applied in the URL. The transformation name and the value should be specified as a key-value pair in the object. Different steps of a [chained transformation](https://docs.imagekit.io/features/image-transformations/chained-transformations) can be specified as different objects of the array. The complete list of supported transformations in the SDK and some examples of using them are given later. If you use a transformation name that is not specified in the SDK, it gets applied as it is in the URL. | -| transformationPostion | Optional. The default value is `path`, which places the transformation string as a path parameter in the URL. It can also be specified as `query`, which adds the transformation string as the query parameter `tr` in the URL. If you use the `src` parameter to create the URL, then the transformation string is always added as a query parameter. | -| queryParameters | Optional. These are the other query parameters that you want to add to the final URL. These can be any query parameters and are not necessarily related to ImageKit. Especially useful if you want to add some versioning parameters to your URLs. | +## TypeScript support -#### Examples of generating URLs +The SDK is written in TypeScript, offering first-class TypeScript support. Enjoy excellent type safety and IntelliSense in your IDE. You can use it in your TypeScript projects without any additional configuration. -**1. Chained Transformations as a query parameter** -``` -var imageURL = imagekit.url({ - path: "/default-image.jpg", - urlEndpoint: "https://ik.imagekit.io/your_imagekit_id/endpoint/", - transformation: [{ - "height": "300", - "width": "400" - }, { - "rotation": 90 - }], - transformationPosition: "query" -}); -``` -``` -https://ik.imagekit.io/your_imagekit_id/endpoint/default-image.jpg?tr=h-300%2Cw-400%3Art-90 -``` - -**2. Sharpening and contrast transforms and a progressive JPG image** - -There are some transforms like [Sharpening](https://docs.imagekit.io/features/image-transformations/image-enhancement-and-color-manipulation) that can be added to the URL with or without any other value. To use such transforms without specifying a value, specify the value as "-" in the transformation object. Otherwise, specify the value that you want to be added to this transformation. - -``` -var imageURL = imagekit.url({ - src: "https://ik.imagekit.io/your_imagekit_id/endpoint/default-image.jpg", - transformation: [{ - "format": "jpg", - "progressive": "true", - "effectSharpen": "-", - "effectContrast": "1" - }] -}); -``` -``` -//Note that because `src` parameter was used, the transformation string gets added as a query parameter `tr` -https://ik.imagekit.io/your_imagekit_id/endpoint/default-image.jpg?tr=f-jpg%2Cpr-true%2Ce-sharpen%2Ce-contrast-1 -``` +To enable type checking in JavaScript projects, add `//@ts-check` at the top of your JavaScript files. This will activate type checking in your IDE. -#### List of supported transformations +### TypeScript and the SDK versioning policy -See the complete list of transformations supported in ImageKit [here](https://docs.imagekit.io/features/image-transformations). The SDK gives a name to each transformation parameter e.g. `height` for `h` and `width` for `w` parameter. It makes your code more readable. If the property does not match any of the following supported options, it is added as it is. - -If you want to generate transformations in your application and add them to the URL as it is, use the `raw` parameter. - -| Supported Transformation Name | Translates to parameter | -|-------------------------------|-------------------------| -| height | h | -| width | w | -| aspectRatio | ar | -| quality | q | -| crop | c | -| cropMode | cm | -| x | x | -| y | y | -| focus | fo | -| format | f | -| radius | r | -| background | bg | -| border | b | -| rotation | rt | -| blur | bl | -| named | n | -| overlayX | ox | -| overlayY | oy | -| overlayFocus | ofo | -| overlayHeight | oh | -| overlayWidth | ow | -| overlayImage | oi | -| overlayImageTrim | oit | -| overlayImageAspectRatio | oiar | -| overlayImageBackground | oibg | -| overlayImageBorder | oib | -| overlayImageDPR | oidpr | -| overlayImageQuality | oiq | -| overlayImageCropping | oic | -| overlayImageTrim | oit | -| overlayText | ot | -| overlayTextFontSize | ots | -| overlayTextFontFamily | otf | -| overlayTextColor | otc | -| overlayTextTransparency | oa | -| overlayAlpha | oa | -| overlayTextTypography | ott | -| overlayBackground | obg | -| overlayTextEncoded | ote | -| overlayTextWidth | otw | -| overlayTextBackground | otbg | -| overlayTextPadding | otp | -| overlayTextInnerAlignment | otia | -| overlayRadius | or | -| progressive | pr | -| lossless | lo | -| trim | t | -| metadata | md | -| colorProfile | cp | -| defaultImage | di | -| dpr | dpr | -| effectSharpen | e-sharpen | -| effectUSM | e-usm | -| effectContrast | e-contrast | -| effectGray | e-grayscale | -| original | orig | -| raw | The string provided in raw will be added in the URL as it is. | - - -### File Upload - -The SDK provides a simple interface using the `.upload()` method to upload files to the ImageKit Media Library. - -The `upload()` method requires mandatory `file` and the `fileName` parameter. In addition, it accepts all the parameters supported by the [ImageKit Upload API](https://docs.imagekit.io/api-reference/upload-file-api/client-side-file-upload). - -Also, ensure that you have specified `authenticationEndpoint` during SDK initialization. The SDK makes an HTTP GET request to this endpoint and expects a JSON response with three fields, i.e. `signature`, `token`, and `expire`. In addition, the SDK adds a query parameter `t` with a random value to ensure that the request URL is unique and the response is not cached in [Safari iOS](https://github.com/imagekit-developer/imagekit-javascript/issues/59). Your backend can ignore this query parameter. - -[Learn how to implement authenticationEndpoint](https://docs.imagekit.io/api-reference/upload-file-api/client-side-file-upload#how-to-implement-authenticationendpoint-endpoint) on your server. - -You can pass other parameters supported by the ImageKit upload API using the same parameter name as specified in the upload API documentation. For example, to specify tags for a file at the time of upload, use the `tags` parameter as specified in the [documentation here](https://docs.imagekit.io/api-reference/upload-file-api/client-side-file-upload). - - -#### Sample usage -```html -
- - -
- - - -``` - -If the upload succeeds, `err` will be `null`, and the `result` will be the same as what is received from ImageKit's servers. -If the upload fails, `err` will be the same as what is received from ImageKit's servers, and the `result` will be null. - -## Tracking upload progress using custom XMLHttpRequest -You can use a custom XMLHttpRequest object as the following to bind `progress` or any other events for a customized implementation. - -```js -var fileSize = file.files[0].size; -var customXHR = new XMLHttpRequest(); -customXHR.upload.addEventListener('progress', function (e) { - if (e.loaded <= fileSize) { - var percent = Math.round(e.loaded / fileSize * 100); - console.log(`Uploaded ${percent}%`); - } - - if(e.loaded == e.total){ - console.log("Upload done"); - } -}); - -imagekit.upload({ - xhr: customXHR, - file: file.files[0], - fileName: "abc1.jpg", - tags: ["tag1"], - extensions: [ - { - name: "aws-auto-tagging", - minConfidence: 80, - maxTags: 10 - } - ] -}).then(result => { - console.log(result); -}).then(error => { - console.log(error); -}) -``` +The TypeScript types in this SDK always reflect the latest shape of the ImageKit API. When we make improvements to the type definitions to better reflect the actual runtime behavior, we may release these changes in minor or patch versions. While these changes align types more closely with reality and are not breaking changes at runtime, they might cause new type errors when you upgrade. -## Access request-id, other response headers, and HTTP status code -You can access `$ResponseMetadata` on success or error object to access the HTTP status code and response headers. +We judge this approach to be better than the alternatives: outdated, inaccurate types, or vastly more frequent major releases that would distract from any truly breaking runtime changes. If you encounter type errors after upgrading, you can resolve them by: -```js -// Success -var response = await imagekit.upload({ - file: file.files[0], - fileName: "abc1.jpg", - tags: ["tag1"], - extensions: [ - { - name: "aws-auto-tagging", - minConfidence: 80, - maxTags: 10 - } - ] -}); -console.log(response.$ResponseMetadata.statusCode); // 200 +- Adding appropriate type guards or assertions +- Updating your code to match the corrected types +- Using `// @ts-ignore` temporarily if you need more time to adjust -// { 'content-length': "300", 'content-type': 'application/json', 'x-request-id': 'ee560df4-d44f-455e-a48e-29dfda49aec5'} -console.log(response.$ResponseMetadata.headers); +Please feel welcome to share your thoughts about the versioning policy in a GitHub issue. -// Error -try { - await imagekit.upload({ - file: file.files[0], - fileName: "abc1.jpg", - tags: ["tag1"], - extensions: [ - { - name: "aws-auto-tagging", - minConfidence: 80, - maxTags: 10 - } - ] - }); -} catch (ex) { - console.log(response.$ResponseMetadata.statusCode); // 400 +## Changelog - // {'content-type': 'application/json', 'x-request-id': 'ee560df4-d44f-455e-a48e-29dfda49aec5'} - console.log(response.$ResponseMetadata.headers); -} \ No newline at end of file +For a detailed history of changes, refer to [CHANGELOG.md](CHANGELOG.md). diff --git a/babel-register.js b/babel-register.js deleted file mode 100644 index 6b72a65..0000000 --- a/babel-register.js +++ /dev/null @@ -1 +0,0 @@ -require("@babel/register")({ extensions: ['.js', '.jsx', '.ts', '.tsx'] }); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 40d6d1e..8b5a77c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6179 +1,2445 @@ { - "name": "imagekit-javascript", - "version": "1.5.4", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@babel/cli": { - "version": "7.11.6", - "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.11.6.tgz", - "integrity": "sha512-+w7BZCvkewSmaRM6H4L2QM3RL90teqEIHDIFXAmrW33+0jhlymnDAEdqVeCZATvxhQuio1ifoGVlJJbIiH9Ffg==", - "dev": true, - "requires": { - "chokidar": "^2.1.8", - "commander": "^4.0.1", - "convert-source-map": "^1.1.0", - "fs-readdir-recursive": "^1.1.0", - "glob": "^7.0.0", - "lodash": "^4.17.19", - "make-dir": "^2.1.0", - "slash": "^2.0.0", - "source-map": "^0.5.0" - } - }, - "@babel/code-frame": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.10.4.tgz", - "integrity": "sha512-vG6SvB6oYEhvgisZNFRmRCUkLz11c7rp+tbNTynGqc6mS1d5ATd/sGyV6W0KZZnXRKMTzZDRgQT3Ou9jhpAfUg==", - "dev": true, - "requires": { - "@babel/highlight": "^7.10.4" - } - }, - "@babel/compat-data": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.11.0.tgz", - "integrity": "sha512-TPSvJfv73ng0pfnEOh17bYMPQbI95+nGWc71Ss4vZdRBHTDqmM9Z8ZV4rYz8Ks7sfzc95n30k6ODIq5UGnXcYQ==", - "dev": true, - "requires": { - "browserslist": "^4.12.0", - "invariant": "^2.2.4", - "semver": "^5.5.0" - } - }, - "@babel/core": { - "version": "7.11.6", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.11.6.tgz", - "integrity": "sha512-Wpcv03AGnmkgm6uS6k8iwhIwTrcP0m17TL1n1sy7qD0qelDu4XNeW0dN0mHfa+Gei211yDaLoEe/VlbXQzM4Bg==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.6", - "@babel/helper-module-transforms": "^7.11.0", - "@babel/helpers": "^7.10.4", - "@babel/parser": "^7.11.5", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.11.5", - "@babel/types": "^7.11.5", - "convert-source-map": "^1.7.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.1", - "json5": "^2.1.2", - "lodash": "^4.17.19", - "resolve": "^1.3.2", - "semver": "^5.4.1", - "source-map": "^0.5.0" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "@babel/generator": { - "version": "7.11.6", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.11.6.tgz", - "integrity": "sha512-DWtQ1PV3r+cLbySoHrwn9RWEgKMBLLma4OBQloPRyDYvc5msJM9kvTLo1YnlJd1P/ZuKbdli3ijr5q3FvAF3uA==", - "dev": true, - "requires": { - "@babel/types": "^7.11.5", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.10.4.tgz", - "integrity": "sha512-XQlqKQP4vXFB7BN8fEEerrmYvHp3fK/rBkRFz9jaJbzK0B1DSfej9Kc7ZzE8Z/OnId1jpJdNAZ3BFQjWG68rcA==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-builder-binary-assignment-operator-visitor": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.10.4.tgz", - "integrity": "sha512-L0zGlFrGWZK4PbT8AszSfLTM5sDU1+Az/En9VrdT8/LmEiJt4zXt+Jve9DCAnQcbqDhCI+29y/L93mrDzddCcg==", - "dev": true, - "requires": { - "@babel/helper-explode-assignable-expression": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-compilation-targets": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.10.4.tgz", - "integrity": "sha512-a3rYhlsGV0UHNDvrtOXBg8/OpfV0OKTkxKPzIplS1zpx7CygDcWWxckxZeDd3gzPzC4kUT0A4nVFDK0wGMh4MQ==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.10.4", - "browserslist": "^4.12.0", - "invariant": "^2.2.4", - "levenary": "^1.1.1", - "semver": "^5.5.0" - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.10.5.tgz", - "integrity": "sha512-0nkdeijB7VlZoLT3r/mY3bUkw3T8WG/hNw+FATs/6+pG2039IJWjTYL0VTISqsNHMUTEnwbVnc89WIJX9Qed0A==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-member-expression-to-functions": "^7.10.5", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.10.4" - } - }, - "@babel/helper-create-regexp-features-plugin": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.10.4.tgz", - "integrity": "sha512-2/hu58IEPKeoLF45DBwx3XFqsbCXmkdAay4spVr2x0jYgRxrSNp+ePwvSsy9g6YSaNDcKIQVPXk1Ov8S2edk2g==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-regex": "^7.10.4", - "regexpu-core": "^4.7.0" - } - }, - "@babel/helper-define-map": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-define-map/-/helper-define-map-7.10.5.tgz", - "integrity": "sha512-fMw4kgFB720aQFXSVaXr79pjjcW5puTCM16+rECJ/plGS+zByelE8l9nCpV1GibxTnFVmUuYG9U8wYfQHdzOEQ==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/types": "^7.10.5", - "lodash": "^4.17.19" - } - }, - "@babel/helper-explode-assignable-expression": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.11.4.tgz", - "integrity": "sha512-ux9hm3zR4WV1Y3xXxXkdG/0gxF9nvI0YVmKVhvK9AfMoaQkemL3sJpXw+Xbz65azo8qJiEz2XVDUpK3KYhH3ZQ==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.10.4.tgz", - "integrity": "sha512-YdaSyz1n8gY44EmN7x44zBn9zQ1Ry2Y+3GTA+3vH6Mizke1Vw0aWDM66FOYEPw8//qKkmqOckrGgTYa+6sceqQ==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.10.4.tgz", - "integrity": "sha512-EkN3YDB+SRDgiIUnNgcmiD361ti+AVbL3f3Henf6dqqUyr5dMsorno0lJWJuLhDhkI5sYEpgj6y9kB8AOU1I2A==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-hoist-variables": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.10.4.tgz", - "integrity": "sha512-wljroF5PgCk2juF69kanHVs6vrLwIPNp6DLD+Lrl3hoQ3PpPPikaDRNFA+0t81NOoMt2DL6WW/mdU8k4k6ZzuA==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.11.0.tgz", - "integrity": "sha512-JbFlKHFntRV5qKw3YC0CvQnDZ4XMwgzzBbld7Ly4Mj4cbFy3KywcR8NtNctRToMWJOVvLINJv525Gd6wwVEx/Q==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-module-imports": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.10.4.tgz", - "integrity": "sha512-nEQJHqYavI217oD9+s5MUBzk6x1IlvoS9WTPfgG43CbMEeStE0v+r+TucWdx8KFGowPGvyOkDT9+7DHedIDnVw==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-module-transforms": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.11.0.tgz", - "integrity": "sha512-02EVu8COMuTRO1TAzdMtpBPbe6aQ1w/8fePD2YgQmxZU4gpNWaL9gK3Jp7dxlkUlUCJOTaSeA+Hrm1BRQwqIhg==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4", - "@babel/helper-simple-access": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/template": "^7.10.4", - "@babel/types": "^7.11.0", - "lodash": "^4.17.19" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.10.4.tgz", - "integrity": "sha512-n3UGKY4VXwXThEiKrgRAoVPBMqeoPgHVqiHZOanAJCG9nQUL2pLRQirUzl0ioKclHGpGqRgIOkgcIJaIWLpygg==", - "dev": true, - "requires": { - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.10.4.tgz", - "integrity": "sha512-O4KCvQA6lLiMU9l2eawBPMf1xPP8xPfB3iEQw150hOVTqj/rfXz0ThTb4HEzqQfs2Bmo5Ay8BzxfzVtBrr9dVg==", - "dev": true - }, - "@babel/helper-regex": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/helper-regex/-/helper-regex-7.10.5.tgz", - "integrity": "sha512-68kdUAzDrljqBrio7DYAEgCoJHxppJOERHOgOrDN7WjOzP0ZQ1LsSDRXcemzVZaLvjaJsJEESb6qt+znNuENDg==", - "dev": true, - "requires": { - "lodash": "^4.17.19" - } - }, - "@babel/helper-remap-async-to-generator": { - "version": "7.11.4", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.11.4.tgz", - "integrity": "sha512-tR5vJ/vBa9wFy3m5LLv2faapJLnDFxNWff2SAYkSE4rLUdbp7CdObYFgI7wK4T/Mj4UzpjPwzR8Pzmr5m7MHGA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-wrap-function": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-replace-supers": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.10.4.tgz", - "integrity": "sha512-sPxZfFXocEymYTdVK1UNmFPBN+Hv5mJkLPsYWwGBxZAxaWfFu+xqp7b6qWD0yjNuNL2VKc6L5M18tOXUP7NU0A==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.10.4", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-simple-access": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.10.4.tgz", - "integrity": "sha512-0fMy72ej/VEvF8ULmX6yb5MtHG4uH4Dbd6I/aHDb/JVg0bbivwt9Wg+h3uMvX+QSFtwr5MeItvazbrc4jtRAXw==", - "dev": true, - "requires": { - "@babel/template": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.11.0.tgz", - "integrity": "sha512-0XIdiQln4Elglgjbwo9wuJpL/K7AGCY26kmEt0+pRP0TAj4jjyNq1MjoRvikrTVqKcx4Gysxt4cXvVFXP/JO2Q==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.11.0.tgz", - "integrity": "sha512-74Vejvp6mHkGE+m+k5vHY93FX2cAtrw1zXrZXRlG4l410Nm9PxfEiVTn1PjDPV5SnmieiueY4AFg2xqhNFuuZg==", - "dev": true, - "requires": { - "@babel/types": "^7.11.0" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.10.4.tgz", - "integrity": "sha512-3U9y+43hz7ZM+rzG24Qe2mufW5KhvFg/NhnNph+i9mgCtdTCtMJuI1TMkrIUiK7Ix4PYlRF9I5dhqaLYA/ADXw==", - "dev": true - }, - "@babel/helper-validator-option": { - "version": "7.12.17", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.12.17.tgz", - "integrity": "sha512-TopkMDmLzq8ngChwRlyjR6raKD6gMSae4JdYDB8bByKreQgG0RBTuKe9LRxW3wFtUnjxOPRKBDwEH6Mg5KeDfw==", - "dev": true - }, - "@babel/helper-wrap-function": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.10.4.tgz", - "integrity": "sha512-6py45WvEF0MhiLrdxtRjKjufwLL1/ob2qDJgg5JgNdojBAZSAKnAjkyOCNug6n+OBl4VW76XjvgSFTdaMcW0Ug==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/helpers": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.10.4.tgz", - "integrity": "sha512-L2gX/XeUONeEbI78dXSrJzGdz4GQ+ZTA/aazfUsFaWjSe95kiCuOZ5HsXvkiw3iwF+mFHSRUfJU8t6YavocdXA==", - "dev": true, - "requires": { - "@babel/template": "^7.10.4", - "@babel/traverse": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/highlight": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.10.4.tgz", - "integrity": "sha512-i6rgnR/YgPEQzZZnbTHHuZdlE8qyoBNalD6F+q4vAFlcMEcqmkoG+mPqJYJCo63qPf74+Y1UZsl3l6f7/RIkmA==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.11.5.tgz", - "integrity": "sha512-X9rD8qqm695vgmeaQ4fvz/o3+Wk4ZzQvSHkDBgpYKxpD4qTAUm88ZKtHkVqIOsYFFbIQ6wQYhC6q7pjqVK0E0Q==", - "dev": true - }, - "@babel/plugin-proposal-async-generator-functions": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.10.5.tgz", - "integrity": "sha512-cNMCVezQbrRGvXJwm9fu/1sJj9bHdGAgKodZdLqOQIpfoH3raqmRPBM17+lh7CzhiKRRBrGtZL9WcjxSoGYUSg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-remap-async-to-generator": "^7.10.4", - "@babel/plugin-syntax-async-generators": "^7.8.0" - } - }, - "@babel/plugin-proposal-class-properties": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.13.0.tgz", - "integrity": "sha512-KnTDjFNC1g+45ka0myZNvSBFLhNCLN+GeGYLDEA8Oq7MZ6yMgfLoIRh86GRT0FjtJhZw8JyUskP9uvj5pHM9Zg==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.13.0", - "@babel/helper-plugin-utils": "^7.13.0" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", - "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.12.13" - } - }, - "@babel/generator": { - "version": "7.14.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.3.tgz", - "integrity": "sha512-bn0S6flG/j0xtQdz3hsjJ624h3W0r3llttBMfyHX3YrZ/KtLYr15bjA0FXkgW7FpvrDuTuElXeVjiKlYRpnOFA==", - "dev": true, - "requires": { - "@babel/types": "^7.14.2", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz", - "integrity": "sha512-7YXfX5wQ5aYM/BOlbSccHDbuXXFPxeoUmfWtz8le2yTkTZc+BxsiEnENFoi2SlmA8ewDkG2LgIMIVzzn2h8kfw==", - "dev": true, - "requires": { - "@babel/types": "^7.12.13" - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.4.tgz", - "integrity": "sha512-idr3pthFlDCpV+p/rMgGLGYIVtazeatrSOQk8YzO2pAepIjQhCN3myeihVg58ax2bbbGK9PUE1reFi7axOYIOw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.12.13", - "@babel/helper-function-name": "^7.14.2", - "@babel/helper-member-expression-to-functions": "^7.13.12", - "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/helper-replace-supers": "^7.14.4", - "@babel/helper-split-export-declaration": "^7.12.13" - } - }, - "@babel/helper-function-name": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz", - "integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.12.13", - "@babel/template": "^7.12.13", - "@babel/types": "^7.14.2" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz", - "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==", - "dev": true, - "requires": { - "@babel/types": "^7.12.13" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz", - "integrity": "sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw==", - "dev": true, - "requires": { - "@babel/types": "^7.13.12" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz", - "integrity": "sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA==", - "dev": true, - "requires": { - "@babel/types": "^7.12.13" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", - "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", - "dev": true - }, - "@babel/helper-replace-supers": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.4.tgz", - "integrity": "sha512-zZ7uHCWlxfEAAOVDYQpEf/uyi1dmeC7fX4nCf2iz9drnCwi1zvwXL3HwWWNXUQEJ1k23yVn3VbddiI9iJEXaTQ==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.13.12", - "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/traverse": "^7.14.2", - "@babel/types": "^7.14.4" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", - "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", - "dev": true, - "requires": { - "@babel/types": "^7.12.13" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", - "dev": true - }, - "@babel/highlight": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", - "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.4.tgz", - "integrity": "sha512-ArliyUsWDUqEGfWcmzpGUzNfLxTdTp6WU4IuP6QFSp9gGfWS6boxFCkJSJ/L4+RG8z/FnIU3WxCk6hPL9SSWeA==", - "dev": true - }, - "@babel/template": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", - "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/parser": "^7.12.13", - "@babel/types": "^7.12.13" - } - }, - "@babel/traverse": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz", - "integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.2", - "@babel/helper-function-name": "^7.14.2", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.2", - "@babel/types": "^7.14.2", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.4.tgz", - "integrity": "sha512-lCj4aIs0xUefJFQnwwQv2Bxg7Omd6bgquZ6LGC+gGMh6/s5qDVfjuCMlDmYQ15SLsWHd9n+X3E75lKIhl5Lkiw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - }, - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "@babel/plugin-proposal-dynamic-import": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.10.4.tgz", - "integrity": "sha512-up6oID1LeidOOASNXgv/CFbgBqTuKJ0cJjz6An5tWD+NVBNlp3VNSBxv2ZdU7SYl3NxJC7agAQDApZusV6uFwQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-dynamic-import": "^7.8.0" - } - }, - "@babel/plugin-proposal-export-namespace-from": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.10.4.tgz", - "integrity": "sha512-aNdf0LY6/3WXkhh0Fdb6Zk9j1NMD8ovj3F6r0+3j837Pn1S1PdNtcwJ5EG9WkVPNHPxyJDaxMaAOVq4eki0qbg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3" - } - }, - "@babel/plugin-proposal-json-strings": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.10.4.tgz", - "integrity": "sha512-fCL7QF0Jo83uy1K0P2YXrfX11tj3lkpN7l4dMv9Y9VkowkhkQDwFHFd8IiwyK5MZjE8UpbgokkgtcReH88Abaw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.0" - } - }, - "@babel/plugin-proposal-logical-assignment-operators": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.11.0.tgz", - "integrity": "sha512-/f8p4z+Auz0Uaf+i8Ekf1iM7wUNLcViFUGiPxKeXvxTSl63B875YPiVdUDdem7hREcI0E0kSpEhS8tF5RphK7Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" - } - }, - "@babel/plugin-proposal-nullish-coalescing-operator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.10.4.tgz", - "integrity": "sha512-wq5n1M3ZUlHl9sqT2ok1T2/MTt6AXE0e1Lz4WzWBr95LsAZ5qDXe4KnFuauYyEyLiohvXFMdbsOTMyLZs91Zlw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0" - } - }, - "@babel/plugin-proposal-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.10.4.tgz", - "integrity": "sha512-73/G7QoRoeNkLZFxsoCCvlg4ezE4eM+57PnOqgaPOozd5myfj7p0muD1mRVJvbUWbOzD+q3No2bWbaKy+DJ8DA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-numeric-separator": "^7.10.4" - } - }, - "@babel/plugin-proposal-object-rest-spread": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.4.tgz", - "integrity": "sha512-AYosOWBlyyXEagrPRfLJ1enStufsr7D1+ddpj8OLi9k7B6+NdZ0t/9V7Fh+wJ4g2Jol8z2JkgczYqtWrZd4vbA==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.14.4", - "@babel/helper-compilation-targets": "^7.14.4", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-transform-parameters": "^7.14.2" - }, - "dependencies": { - "@babel/compat-data": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.4.tgz", - "integrity": "sha512-i2wXrWQNkH6JplJQGn3Rd2I4Pij8GdHkXwHMxm+zV5YG/Jci+bCNrWZEWC4o+umiDkRrRs4dVzH3X4GP7vyjQQ==", - "dev": true - }, - "@babel/helper-compilation-targets": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.14.4.tgz", - "integrity": "sha512-JgdzOYZ/qGaKTVkn5qEDV/SXAh8KcyUVkCoSWGN8T3bwrgd6m+/dJa2kVGi6RJYJgEYPBdZ84BZp9dUjNWkBaA==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.14.4", - "@babel/helper-validator-option": "^7.12.17", - "browserslist": "^4.16.6", - "semver": "^6.3.0" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", - "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", - "dev": true - }, - "@babel/plugin-transform-parameters": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.14.2.tgz", - "integrity": "sha512-NxoVmA3APNCC1JdMXkdYXuQS+EMdqy0vIwyDHeKHiJKRxmp1qGSdb0JLEIoPRhkx6H/8Qi3RJ3uqOCYw8giy9A==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.13.0" - } - }, - "electron-to-chromium": { - "version": "1.3.743", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.743.tgz", - "integrity": "sha512-K2wXfo9iZQzNJNx67+Pld0DRF+9bYinj62gXCdgPhcu1vidwVuLPHQPPFnCdO55njWigXXpfBiT90jGUPbw8Zg==" - }, - "node-releases": { - "version": "1.1.72", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.72.tgz", - "integrity": "sha512-LLUo+PpH3dU6XizX3iVoubUNheF/owjXCZZ5yACDxNnPtgFuludV1ZL3ayK1kVep42Rmm0+R9/Y60NQbZ2bifw==" - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "@babel/plugin-proposal-optional-catch-binding": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.10.4.tgz", - "integrity": "sha512-LflT6nPh+GK2MnFiKDyLiqSqVHkQnVf7hdoAvyTnnKj9xB3docGRsdPuxp6qqqW19ifK3xgc9U5/FwrSaCNX5g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0" - } - }, - "@babel/plugin-proposal-optional-chaining": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.11.0.tgz", - "integrity": "sha512-v9fZIu3Y8562RRwhm1BbMRxtqZNFmFA2EG+pT2diuU8PT3H6T/KXoZ54KgYisfOFZHV6PfvAiBIZ9Rcz+/JCxA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0" - } - }, - "@babel/plugin-proposal-private-methods": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.10.4.tgz", - "integrity": "sha512-wh5GJleuI8k3emgTg5KkJK6kHNsGEr0uBTDBuQUBJwckk9xs1ez79ioheEVVxMLyPscB0LfkbVHslQqIzWV6Bw==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-proposal-unicode-property-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.10.4.tgz", - "integrity": "sha512-H+3fOgPnEXFL9zGYtKQe4IDOPKYlZdF1kqFDQRRb8PK4B8af1vAGK04tF5iQAAsui+mHNBQSAtd2/ndEDe9wuA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-async-generators": { - "version": "7.8.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", - "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-class-properties": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.10.4.tgz", - "integrity": "sha512-GCSBF7iUle6rNugfURwNmCGG3Z/2+opxAMLs1nND4bhEG5PuxTIggDBoeYYSujAlLtsupzOHYJQgPS3pivwXIA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-dynamic-import": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz", - "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-export-namespace-from": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", - "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.3" - } - }, - "@babel/plugin-syntax-json-strings": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", - "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-nullish-coalescing-operator": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz", - "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-numeric-separator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", - "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-object-rest-spread": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", - "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-catch-binding": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz", - "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-optional-chaining": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz", - "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.8.0" - } - }, - "@babel/plugin-syntax-top-level-await": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.10.4.tgz", - "integrity": "sha512-ni1brg4lXEmWyafKr0ccFWkJG0CeMt4WV1oyeBW6EFObF4oOHclbkj5cARxAPQyAQ2UTuplJyK4nfkXIMMFvsQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-syntax-typescript": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.12.13.tgz", - "integrity": "sha512-cHP3u1JiUiG2LFDKbXnwVad81GvfyIOmCD6HIEId6ojrY0Drfy2q1jw7BwN7dE84+kTnBjLkXoL3IEy/3JPu2w==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.12.13" - }, - "dependencies": { - "@babel/helper-plugin-utils": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", - "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", - "dev": true - } - } - }, - "@babel/plugin-transform-arrow-functions": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.10.4.tgz", - "integrity": "sha512-9J/oD1jV0ZCBcgnoFWFq1vJd4msoKb/TCpGNFyyLt0zABdcvgK3aYikZ8HjzB14c26bc7E3Q1yugpwGy2aTPNA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-async-to-generator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.10.4.tgz", - "integrity": "sha512-F6nREOan7J5UXTLsDsZG3DXmZSVofr2tGNwfdrVwkDWHfQckbQXnXSPfD7iO+c/2HGqycwyLST3DnZ16n+cBJQ==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-remap-async-to-generator": "^7.10.4" - } - }, - "@babel/plugin-transform-block-scoped-functions": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.10.4.tgz", - "integrity": "sha512-WzXDarQXYYfjaV1szJvN3AD7rZgZzC1JtjJZ8dMHUyiK8mxPRahynp14zzNjU3VkPqPsO38CzxiWO1c9ARZ8JA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-block-scoping": { - "version": "7.11.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.11.1.tgz", - "integrity": "sha512-00dYeDE0EVEHuuM+26+0w/SCL0BH2Qy7LwHuI4Hi4MH5gkC8/AqMN5uWFJIsoXZrAphiMm1iXzBw6L2T+eA0ew==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-classes": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.10.4.tgz", - "integrity": "sha512-2oZ9qLjt161dn1ZE0Ms66xBncQH4In8Sqw1YWgBUZuGVJJS5c0OFZXL6dP2MRHrkU/eKhWg8CzFJhRQl50rQxA==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-define-map": "^7.10.4", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-optimise-call-expression": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.10.4", - "globals": "^11.1.0" - } - }, - "@babel/plugin-transform-computed-properties": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.10.4.tgz", - "integrity": "sha512-JFwVDXcP/hM/TbyzGq3l/XWGut7p46Z3QvqFMXTfk6/09m7xZHJUN9xHfsv7vqqD4YnfI5ueYdSJtXqqBLyjBw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-destructuring": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.10.4.tgz", - "integrity": "sha512-+WmfvyfsyF603iPa6825mq6Qrb7uLjTOsa3XOFzlYcYDHSS4QmpOWOL0NNBY5qMbvrcf3tq0Cw+v4lxswOBpgA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-dotall-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.10.4.tgz", - "integrity": "sha512-ZEAVvUTCMlMFAbASYSVQoxIbHm2OkG2MseW6bV2JjIygOjdVv8tuxrCTzj1+Rynh7ODb8GivUy7dzEXzEhuPaA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-duplicate-keys": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.10.4.tgz", - "integrity": "sha512-GL0/fJnmgMclHiBTTWXNlYjYsA7rDrtsazHG6mglaGSTh0KsrW04qml+Bbz9FL0LcJIRwBWL5ZqlNHKTkU3xAA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-exponentiation-operator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.10.4.tgz", - "integrity": "sha512-S5HgLVgkBcRdyQAHbKj+7KyuWx8C6t5oETmUuwz1pt3WTWJhsUV0WIIXuVvfXMxl/QQyHKlSCNNtaIamG8fysw==", - "dev": true, - "requires": { - "@babel/helper-builder-binary-assignment-operator-visitor": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-for-of": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.10.4.tgz", - "integrity": "sha512-ItdQfAzu9AlEqmusA/65TqJ79eRcgGmpPPFvBnGILXZH975G0LNjP1yjHvGgfuCxqrPPueXOPe+FsvxmxKiHHQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-function-name": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.10.4.tgz", - "integrity": "sha512-OcDCq2y5+E0dVD5MagT5X+yTRbcvFjDI2ZVAottGH6tzqjx/LKpgkUepu3hp/u4tZBzxxpNGwLsAvGBvQ2mJzg==", - "dev": true, - "requires": { - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-literals": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.10.4.tgz", - "integrity": "sha512-Xd/dFSTEVuUWnyZiMu76/InZxLTYilOSr1UlHV+p115Z/Le2Fi1KXkJUYz0b42DfndostYlPub3m8ZTQlMaiqQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-member-expression-literals": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.10.4.tgz", - "integrity": "sha512-0bFOvPyAoTBhtcJLr9VcwZqKmSjFml1iVxvPL0ReomGU53CX53HsM4h2SzckNdkQcHox1bpAqzxBI1Y09LlBSw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-modules-amd": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.10.5.tgz", - "integrity": "sha512-elm5uruNio7CTLFItVC/rIzKLfQ17+fX7EVz5W0TMgIHFo1zY0Ozzx+lgwhL4plzl8OzVn6Qasx5DeEFyoNiRw==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.10.5", - "@babel/helper-plugin-utils": "^7.10.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-commonjs": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.10.4.tgz", - "integrity": "sha512-Xj7Uq5o80HDLlW64rVfDBhao6OX89HKUmb+9vWYaLXBZOma4gA6tw4Ni1O5qVDoZWUV0fxMYA0aYzOawz0l+1w==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-simple-access": "^7.10.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-systemjs": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.10.5.tgz", - "integrity": "sha512-f4RLO/OL14/FP1AEbcsWMzpbUz6tssRaeQg11RH1BP/XnPpRoVwgeYViMFacnkaw4k4wjRSjn3ip1Uw9TaXuMw==", - "dev": true, - "requires": { - "@babel/helper-hoist-variables": "^7.10.4", - "@babel/helper-module-transforms": "^7.10.5", - "@babel/helper-plugin-utils": "^7.10.4", - "babel-plugin-dynamic-import-node": "^2.3.3" - } - }, - "@babel/plugin-transform-modules-umd": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.10.4.tgz", - "integrity": "sha512-mohW5q3uAEt8T45YT7Qc5ws6mWgJAaL/8BfWD9Dodo1A3RKWli8wTS+WiQ/knF+tXlPirW/1/MqzzGfCExKECA==", - "dev": true, - "requires": { - "@babel/helper-module-transforms": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.10.4.tgz", - "integrity": "sha512-V6LuOnD31kTkxQPhKiVYzYC/Jgdq53irJC/xBSmqcNcqFGV+PER4l6rU5SH2Vl7bH9mLDHcc0+l9HUOe4RNGKA==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.4" - } - }, - "@babel/plugin-transform-new-target": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.10.4.tgz", - "integrity": "sha512-YXwWUDAH/J6dlfwqlWsztI2Puz1NtUAubXhOPLQ5gjR/qmQ5U96DY4FQO8At33JN4XPBhrjB8I4eMmLROjjLjw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-object-super": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.10.4.tgz", - "integrity": "sha512-5iTw0JkdRdJvr7sY0vHqTpnruUpTea32JHmq/atIWqsnNussbRzjEDyWep8UNztt1B5IusBYg8Irb0bLbiEBCQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-replace-supers": "^7.10.4" - } - }, - "@babel/plugin-transform-parameters": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.10.5.tgz", - "integrity": "sha512-xPHwUj5RdFV8l1wuYiu5S9fqWGM2DrYc24TMvUiRrPVm+SM3XeqU9BcokQX/kEUe+p2RBwy+yoiR1w/Blq6ubw==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-property-literals": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.10.4.tgz", - "integrity": "sha512-ofsAcKiUxQ8TY4sScgsGeR2vJIsfrzqvFb9GvJ5UdXDzl+MyYCaBj/FGzXuv7qE0aJcjWMILny1epqelnFlz8g==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-regenerator": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.10.4.tgz", - "integrity": "sha512-3thAHwtor39A7C04XucbMg17RcZ3Qppfxr22wYzZNcVIkPHfpM9J0SO8zuCV6SZa265kxBJSrfKTvDCYqBFXGw==", - "dev": true, - "requires": { - "regenerator-transform": "^0.14.2" - } - }, - "@babel/plugin-transform-reserved-words": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.10.4.tgz", - "integrity": "sha512-hGsw1O6Rew1fkFbDImZIEqA8GoidwTAilwCyWqLBM9f+e/u/sQMQu7uX6dyokfOayRuuVfKOW4O7HvaBWM+JlQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-shorthand-properties": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.10.4.tgz", - "integrity": "sha512-AC2K/t7o07KeTIxMoHneyX90v3zkm5cjHJEokrPEAGEy3UCp8sLKfnfOIGdZ194fyN4wfX/zZUWT9trJZ0qc+Q==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-spread": { - "version": "7.11.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.11.0.tgz", - "integrity": "sha512-UwQYGOqIdQJe4aWNyS7noqAnN2VbaczPLiEtln+zPowRNlD+79w3oi2TWfYe0eZgd+gjZCbsydN7lzWysDt+gw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-skip-transparent-expression-wrappers": "^7.11.0" - } - }, - "@babel/plugin-transform-sticky-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.10.4.tgz", - "integrity": "sha512-Ddy3QZfIbEV0VYcVtFDCjeE4xwVTJWTmUtorAJkn6u/92Z/nWJNV+mILyqHKrUxXYKA2EoCilgoPePymKL4DvQ==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/helper-regex": "^7.10.4" - } - }, - "@babel/plugin-transform-template-literals": { - "version": "7.10.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.10.5.tgz", - "integrity": "sha512-V/lnPGIb+KT12OQikDvgSuesRX14ck5FfJXt6+tXhdkJ+Vsd0lDCVtF6jcB4rNClYFzaB2jusZ+lNISDk2mMMw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-typeof-symbol": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.10.4.tgz", - "integrity": "sha512-QqNgYwuuW0y0H+kUE/GWSR45t/ccRhe14Fs/4ZRouNNQsyd4o3PG4OtHiIrepbM2WKUBDAXKCAK/Lk4VhzTaGA==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-typescript": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.14.4.tgz", - "integrity": "sha512-WYdcGNEO7mCCZ2XzRlxwGj3PgeAr50ifkofOUC/+IN/GzKLB+biDPVBUAQN2C/dVZTvEXCp80kfQ1FFZPrwykQ==", - "dev": true, - "requires": { - "@babel/helper-create-class-features-plugin": "^7.14.4", - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/plugin-syntax-typescript": "^7.12.13" - }, - "dependencies": { - "@babel/code-frame": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", - "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", - "dev": true, - "requires": { - "@babel/highlight": "^7.12.13" - } - }, - "@babel/generator": { - "version": "7.14.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.14.3.tgz", - "integrity": "sha512-bn0S6flG/j0xtQdz3hsjJ624h3W0r3llttBMfyHX3YrZ/KtLYr15bjA0FXkgW7FpvrDuTuElXeVjiKlYRpnOFA==", - "dev": true, - "requires": { - "@babel/types": "^7.14.2", - "jsesc": "^2.5.1", - "source-map": "^0.5.0" - } - }, - "@babel/helper-annotate-as-pure": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.12.13.tgz", - "integrity": "sha512-7YXfX5wQ5aYM/BOlbSccHDbuXXFPxeoUmfWtz8le2yTkTZc+BxsiEnENFoi2SlmA8ewDkG2LgIMIVzzn2h8kfw==", - "dev": true, - "requires": { - "@babel/types": "^7.12.13" - } - }, - "@babel/helper-create-class-features-plugin": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.14.4.tgz", - "integrity": "sha512-idr3pthFlDCpV+p/rMgGLGYIVtazeatrSOQk8YzO2pAepIjQhCN3myeihVg58ax2bbbGK9PUE1reFi7axOYIOw==", - "dev": true, - "requires": { - "@babel/helper-annotate-as-pure": "^7.12.13", - "@babel/helper-function-name": "^7.14.2", - "@babel/helper-member-expression-to-functions": "^7.13.12", - "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/helper-replace-supers": "^7.14.4", - "@babel/helper-split-export-declaration": "^7.12.13" - } - }, - "@babel/helper-function-name": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.14.2.tgz", - "integrity": "sha512-NYZlkZRydxw+YT56IlhIcS8PAhb+FEUiOzuhFTfqDyPmzAhRge6ua0dQYT/Uh0t/EDHq05/i+e5M2d4XvjgarQ==", - "dev": true, - "requires": { - "@babel/helper-get-function-arity": "^7.12.13", - "@babel/template": "^7.12.13", - "@babel/types": "^7.14.2" - } - }, - "@babel/helper-get-function-arity": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-get-function-arity/-/helper-get-function-arity-7.12.13.tgz", - "integrity": "sha512-DjEVzQNz5LICkzN0REdpD5prGoidvbdYk1BVgRUOINaWJP2t6avB27X1guXK1kXNrX0WMfsrm1A/ZBthYuIMQg==", - "dev": true, - "requires": { - "@babel/types": "^7.12.13" - } - }, - "@babel/helper-member-expression-to-functions": { - "version": "7.13.12", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.13.12.tgz", - "integrity": "sha512-48ql1CLL59aKbU94Y88Xgb2VFy7a95ykGRbJJaaVv+LX5U8wFpLfiGXJJGUozsmA1oEh/o5Bp60Voq7ACyA/Sw==", - "dev": true, - "requires": { - "@babel/types": "^7.13.12" - } - }, - "@babel/helper-optimise-call-expression": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.12.13.tgz", - "integrity": "sha512-BdWQhoVJkp6nVjB7nkFWcn43dkprYauqtk++Py2eaf/GRDFm5BxRqEIZCiHlZUGAVmtwKcsVL1dC68WmzeFmiA==", - "dev": true, - "requires": { - "@babel/types": "^7.12.13" - } - }, - "@babel/helper-plugin-utils": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", - "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", - "dev": true - }, - "@babel/helper-replace-supers": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.14.4.tgz", - "integrity": "sha512-zZ7uHCWlxfEAAOVDYQpEf/uyi1dmeC7fX4nCf2iz9drnCwi1zvwXL3HwWWNXUQEJ1k23yVn3VbddiI9iJEXaTQ==", - "dev": true, - "requires": { - "@babel/helper-member-expression-to-functions": "^7.13.12", - "@babel/helper-optimise-call-expression": "^7.12.13", - "@babel/traverse": "^7.14.2", - "@babel/types": "^7.14.4" - } - }, - "@babel/helper-split-export-declaration": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.12.13.tgz", - "integrity": "sha512-tCJDltF83htUtXx5NLcaDqRmknv652ZWCHyoTETf1CXYJdPC7nohZohjUgieXhv0hTJdRf2FjDueFehdNucpzg==", - "dev": true, - "requires": { - "@babel/types": "^7.12.13" - } - }, - "@babel/helper-validator-identifier": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", - "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", - "dev": true - }, - "@babel/highlight": { - "version": "7.14.0", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", - "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - } - }, - "@babel/parser": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.14.4.tgz", - "integrity": "sha512-ArliyUsWDUqEGfWcmzpGUzNfLxTdTp6WU4IuP6QFSp9gGfWS6boxFCkJSJ/L4+RG8z/FnIU3WxCk6hPL9SSWeA==", - "dev": true - }, - "@babel/template": { - "version": "7.12.13", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.12.13.tgz", - "integrity": "sha512-/7xxiGA57xMo/P2GVvdEumr8ONhFOhfgq2ihK3h1e6THqzTAkHbkXgB0xI9yeTfIUoH3+oAeHhqm/I43OTbbjA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/parser": "^7.12.13", - "@babel/types": "^7.12.13" - } - }, - "@babel/traverse": { - "version": "7.14.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.14.2.tgz", - "integrity": "sha512-TsdRgvBFHMyHOOzcP9S6QU0QQtjxlRpEYOy3mcCO5RgmC305ki42aSAmfZEMSSYBla2oZ9BMqYlncBaKmD/7iA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.12.13", - "@babel/generator": "^7.14.2", - "@babel/helper-function-name": "^7.14.2", - "@babel/helper-split-export-declaration": "^7.12.13", - "@babel/parser": "^7.14.2", - "@babel/types": "^7.14.2", - "debug": "^4.1.0", - "globals": "^11.1.0" - } - }, - "@babel/types": { - "version": "7.14.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.14.4.tgz", - "integrity": "sha512-lCj4aIs0xUefJFQnwwQv2Bxg7Omd6bgquZ6LGC+gGMh6/s5qDVfjuCMlDmYQ15SLsWHd9n+X3E75lKIhl5Lkiw==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.14.0", - "to-fast-properties": "^2.0.0" - } - }, - "debug": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.1.tgz", - "integrity": "sha512-doEwdvm4PCeK4K3RQN2ZC2BYUBaxwLARCqZmMjtF8a51J2Rb0xpVloFRnCODwqjpwnAoao4pelN8l3RJdv3gRQ==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "@babel/plugin-transform-unicode-escapes": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.10.4.tgz", - "integrity": "sha512-y5XJ9waMti2J+e7ij20e+aH+fho7Wb7W8rNuu72aKRwCHFqQdhkdU2lo3uZ9tQuboEJcUFayXdARhcxLQ3+6Fg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/plugin-transform-unicode-regex": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.10.4.tgz", - "integrity": "sha512-wNfsc4s8N2qnIwpO/WP2ZiSyjfpTamT2C9V9FDH/Ljub9zw6P3SjkXcFmc0RQUt96k2fmIvtla2MMjgTwIAC+A==", - "dev": true, - "requires": { - "@babel/helper-create-regexp-features-plugin": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4" - } - }, - "@babel/preset-env": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.11.5.tgz", - "integrity": "sha512-kXqmW1jVcnB2cdueV+fyBM8estd5mlNfaQi6lwLgRwCby4edpavgbFhiBNjmWA3JpB/yZGSISa7Srf+TwxDQoA==", - "dev": true, - "requires": { - "@babel/compat-data": "^7.11.0", - "@babel/helper-compilation-targets": "^7.10.4", - "@babel/helper-module-imports": "^7.10.4", - "@babel/helper-plugin-utils": "^7.10.4", - "@babel/plugin-proposal-async-generator-functions": "^7.10.4", - "@babel/plugin-proposal-class-properties": "^7.10.4", - "@babel/plugin-proposal-dynamic-import": "^7.10.4", - "@babel/plugin-proposal-export-namespace-from": "^7.10.4", - "@babel/plugin-proposal-json-strings": "^7.10.4", - "@babel/plugin-proposal-logical-assignment-operators": "^7.11.0", - "@babel/plugin-proposal-nullish-coalescing-operator": "^7.10.4", - "@babel/plugin-proposal-numeric-separator": "^7.10.4", - "@babel/plugin-proposal-object-rest-spread": "^7.11.0", - "@babel/plugin-proposal-optional-catch-binding": "^7.10.4", - "@babel/plugin-proposal-optional-chaining": "^7.11.0", - "@babel/plugin-proposal-private-methods": "^7.10.4", - "@babel/plugin-proposal-unicode-property-regex": "^7.10.4", - "@babel/plugin-syntax-async-generators": "^7.8.0", - "@babel/plugin-syntax-class-properties": "^7.10.4", - "@babel/plugin-syntax-dynamic-import": "^7.8.0", - "@babel/plugin-syntax-export-namespace-from": "^7.8.3", - "@babel/plugin-syntax-json-strings": "^7.8.0", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.0", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.0", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.0", - "@babel/plugin-syntax-optional-chaining": "^7.8.0", - "@babel/plugin-syntax-top-level-await": "^7.10.4", - "@babel/plugin-transform-arrow-functions": "^7.10.4", - "@babel/plugin-transform-async-to-generator": "^7.10.4", - "@babel/plugin-transform-block-scoped-functions": "^7.10.4", - "@babel/plugin-transform-block-scoping": "^7.10.4", - "@babel/plugin-transform-classes": "^7.10.4", - "@babel/plugin-transform-computed-properties": "^7.10.4", - "@babel/plugin-transform-destructuring": "^7.10.4", - "@babel/plugin-transform-dotall-regex": "^7.10.4", - "@babel/plugin-transform-duplicate-keys": "^7.10.4", - "@babel/plugin-transform-exponentiation-operator": "^7.10.4", - "@babel/plugin-transform-for-of": "^7.10.4", - "@babel/plugin-transform-function-name": "^7.10.4", - "@babel/plugin-transform-literals": "^7.10.4", - "@babel/plugin-transform-member-expression-literals": "^7.10.4", - "@babel/plugin-transform-modules-amd": "^7.10.4", - "@babel/plugin-transform-modules-commonjs": "^7.10.4", - "@babel/plugin-transform-modules-systemjs": "^7.10.4", - "@babel/plugin-transform-modules-umd": "^7.10.4", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.10.4", - "@babel/plugin-transform-new-target": "^7.10.4", - "@babel/plugin-transform-object-super": "^7.10.4", - "@babel/plugin-transform-parameters": "^7.10.4", - "@babel/plugin-transform-property-literals": "^7.10.4", - "@babel/plugin-transform-regenerator": "^7.10.4", - "@babel/plugin-transform-reserved-words": "^7.10.4", - "@babel/plugin-transform-shorthand-properties": "^7.10.4", - "@babel/plugin-transform-spread": "^7.11.0", - "@babel/plugin-transform-sticky-regex": "^7.10.4", - "@babel/plugin-transform-template-literals": "^7.10.4", - "@babel/plugin-transform-typeof-symbol": "^7.10.4", - "@babel/plugin-transform-unicode-escapes": "^7.10.4", - "@babel/plugin-transform-unicode-regex": "^7.10.4", - "@babel/preset-modules": "^0.1.3", - "@babel/types": "^7.11.5", - "browserslist": "^4.12.0", - "core-js-compat": "^3.6.2", - "invariant": "^2.2.2", - "levenary": "^1.1.1", - "semver": "^5.5.0" - } - }, - "@babel/preset-modules": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.4.tgz", - "integrity": "sha512-J36NhwnfdzpmH41M1DrnkkgAqhZaqr/NBdPfQ677mLzlaXo+oDiv1deyCDtgAhz8p328otdob0Du7+xgHGZbKg==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/plugin-proposal-unicode-property-regex": "^7.4.4", - "@babel/plugin-transform-dotall-regex": "^7.4.4", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - } - }, - "@babel/preset-typescript": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.13.0.tgz", - "integrity": "sha512-LXJwxrHy0N3f6gIJlYbLta1D9BDtHpQeqwzM0LIfjDlr6UE/D5Mc7W4iDiQzaE+ks0sTjT26ArcHWnJVt0QiHw==", - "dev": true, - "requires": { - "@babel/helper-plugin-utils": "^7.13.0", - "@babel/helper-validator-option": "^7.12.17", - "@babel/plugin-transform-typescript": "^7.13.0" - }, - "dependencies": { - "@babel/helper-plugin-utils": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.13.0.tgz", - "integrity": "sha512-ZPafIPSwzUlAoWT8DKs1W2VyF2gOWthGd5NGFMsBcMMol+ZhK+EQY/e6V96poa6PA/Bh+C9plWN0hXO1uB8AfQ==", - "dev": true - } - } - }, - "@babel/register": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel%2fregister/-/register-7.14.5.tgz", - "integrity": "sha512-TjJpGz/aDjFGWsItRBQMOFTrmTI9tr79CHOK+KIvLeCkbxuOAk2M5QHjvruIMGoo9OuccMh5euplPzc5FjAKGg==", - "dev": true, - "requires": { - "clone-deep": "^4.0.1", - "find-cache-dir": "^2.0.0", - "make-dir": "^2.1.0", - "pirates": "^4.0.0", - "source-map-support": "^0.5.16" - }, - "dependencies": { - "find-cache-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", - "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^2.0.0", - "pkg-dir": "^3.0.0" - } - }, - "pkg-dir": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", - "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", - "dev": true, - "requires": { - "find-up": "^3.0.0" - } - } - } - }, - "@babel/runtime": { - "version": "7.11.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.11.2.tgz", - "integrity": "sha512-TeWkU52so0mPtDcaCTxNBI/IHiz0pZgr8VEFqXFtZWpYD08ZB6FaSwVAS8MKRQAP3bYKiVjwysOJgMFY28o6Tw==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.4" - } - }, - "@babel/template": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.10.4.tgz", - "integrity": "sha512-ZCjD27cGJFUB6nmCB1Enki3r+L5kJveX9pq1SvAUKoICy6CZ9yD8xO086YXdYhvNjBdnekm4ZnaP5yC8Cs/1tA==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/parser": "^7.10.4", - "@babel/types": "^7.10.4" - } - }, - "@babel/traverse": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.11.5.tgz", - "integrity": "sha512-EjiPXt+r7LiCZXEfRpSJd+jUMnBd4/9OUv7Nx3+0u9+eimMwJmG0Q98lw4/289JCoxSE8OolDMNZaaF/JZ69WQ==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.10.4", - "@babel/generator": "^7.11.5", - "@babel/helper-function-name": "^7.10.4", - "@babel/helper-split-export-declaration": "^7.11.0", - "@babel/parser": "^7.11.5", - "@babel/types": "^7.11.5", - "debug": "^4.1.0", - "globals": "^11.1.0", - "lodash": "^4.17.19" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "@babel/types": { - "version": "7.11.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.11.5.tgz", - "integrity": "sha512-bvM7Qz6eKnJVFIn+1LPtjlBFPVN5jNDc1XmN15vWe7Q3DPBufWWsLiIvUu7xW87uTG6QoggpIDnUgLQvPheU+Q==", - "dev": true, - "requires": { - "@babel/helper-validator-identifier": "^7.10.4", - "lodash": "^4.17.19", - "to-fast-properties": "^2.0.0" - } - }, - "@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "requires": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - } - } - }, - "@istanbuljs/schema": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.2.tgz", - "integrity": "sha512-tsAQNx32a8CoFhjhijUIhI4kccIAgmGhy8LZMZgGfmXcpMbPRUqn5LWmgRttILi6yeGmBJd2xsPkFMs0PzgPCw==", - "dev": true - }, - "@rollup/plugin-babel": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.2.1.tgz", - "integrity": "sha512-Jd7oqFR2dzZJ3NWANDyBjwTtX/lYbZpVcmkHrfQcpvawHs9E4c0nYk5U2mfZ6I/DZcIvy506KZJi54XK/jxH7A==", - "dev": true, - "requires": { - "@babel/helper-module-imports": "^7.10.4", - "@rollup/pluginutils": "^3.1.0" - } - }, - "@rollup/plugin-json": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-4.1.0.tgz", - "integrity": "sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^3.0.8" - } - }, - "@rollup/plugin-node-resolve": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-8.4.0.tgz", - "integrity": "sha512-LFqKdRLn0ShtQyf6SBYO69bGE1upV6wUhBX0vFOUnLAyzx5cwp8svA0eHUnu8+YU57XOkrMtfG63QOpQx25pHQ==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^3.1.0", - "@types/resolve": "1.17.1", - "builtin-modules": "^3.1.0", - "deep-freeze": "^0.0.1", - "deepmerge": "^4.2.2", - "is-module": "^1.0.0", - "resolve": "^1.17.0" - } - }, - "@rollup/plugin-typescript": { - "version": "8.2.1", - "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-8.2.1.tgz", - "integrity": "sha512-Qd2E1pleDR4bwyFxqbjt4eJf+wB0UKVMLc7/BAFDGVdAXQMCsD4DUv5/7/ww47BZCYxWtJqe1Lo0KVNswBJlRw==", - "dev": true, - "requires": { - "@rollup/pluginutils": "^3.1.0", - "resolve": "^1.17.0" - } - }, - "@rollup/pluginutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", - "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", - "dev": true, - "requires": { - "@types/estree": "0.0.39", - "estree-walker": "^1.0.1", - "picomatch": "^2.2.2" - } - }, - "@sinonjs/commons": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-1.8.1.tgz", - "integrity": "sha512-892K+kWUUi3cl+LlqEWIDrhvLgdL79tECi8JZUyq6IviKy/DNhuzCRlbHUjxK89f4ypPMMaFnFuR9Ie6DoIMsw==", - "dev": true, - "requires": { - "type-detect": "4.0.8" - } - }, - "@sinonjs/formatio": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/formatio/-/formatio-4.0.1.tgz", - "integrity": "sha512-asIdlLFrla/WZybhm0C8eEzaDNNrzymiTqHMeJl6zPW2881l3uuVRpm0QlRQEjqYWv6CcKMGYME3LbrLJsORBw==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1", - "@sinonjs/samsam": "^4.2.0" - } - }, - "@sinonjs/samsam": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-4.2.2.tgz", - "integrity": "sha512-z9o4LZUzSD9Hl22zV38aXNykgFeVj8acqfFabCY6FY83n/6s/XwNJyYYldz6/9lBJanpno9h+oL6HTISkviweA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.6.0", - "lodash.get": "^4.4.2", - "type-detect": "^4.0.8" - } - }, - "@sinonjs/text-encoding": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.1.tgz", - "integrity": "sha512-+iTbntw2IZPb/anVDbypzfQa+ay64MW0Zo8aJ8gZPWMMK6/OubMVb6lUPMagqjOPnmtauXnFCACVl3O7ogjeqQ==", - "dev": true - }, - "@tootallnate/once": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", - "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==", - "dev": true - }, - "@tsconfig/node10": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.7.tgz", - "integrity": "sha512-aBvUmXLQbayM4w3A8TrjwrXs4DZ8iduJnuJLLRGdkWlyakCf1q6uHZJBzXoRA/huAEknG5tcUyQxN3A+In5euQ==", - "dev": true - }, - "@tsconfig/node12": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.7.tgz", - "integrity": "sha512-dgasobK/Y0wVMswcipr3k0HpevxFJLijN03A8mYfEPvWvOs14v0ZlYTR4kIgMx8g4+fTyTFv8/jLCIfRqLDJ4A==", - "dev": true - }, - "@tsconfig/node14": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.0.tgz", - "integrity": "sha512-RKkL8eTdPv6t5EHgFKIVQgsDapugbuOptNd9OOunN/HAkzmmTnZELx1kNCK0rSdUYGmiFMM3rRQMAWiyp023LQ==", - "dev": true - }, - "@tsconfig/node16": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.1.tgz", - "integrity": "sha512-FTgBI767POY/lKNDNbIzgAX6miIDBs6NTCbdlDb8TrWovHsSvaVIZDlTqym29C6UqhzwcJx4CYr+AlrMywA0cA==", - "dev": true - }, - "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", - "dev": true - }, - "@types/node": { - "version": "15.6.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-15.6.1.tgz", - "integrity": "sha512-7EIraBEyRHEe7CH+Fm1XvgqU6uwZN8Q7jppJGcqjROMT29qhAuuOxYB1uEY5UMYQKEmA5D+5tBnhdaPXSsLONA==", - "dev": true - }, - "@types/resolve": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", - "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", - "dev": true, - "requires": { - "@types/node": "*" - } - }, - "agent-base": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.1.tgz", - "integrity": "sha512-01q25QQDwLSsyfhrKbn8yuur+JNw0H+0Y4JiGIKd3z9aYk/w/2kxD/Upc+t2ZBBSUNff50VjPsSW2YxM8QYKVg==", - "dev": true, - "requires": { - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "dev": true, - "requires": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" - } - }, - "ansi-colors": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz", - "integrity": "sha512-LEHHyuhlPY3TmuUYMh2oz89lTShfvgbmzaBcxve9t/9Wuy7Dwf4yoAKcND7KFT1HAQfqZ12qtc+DUrBMeKF9nw==", - "dev": true - }, - "ansi-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", - "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", - "dev": true - }, - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "anymatch": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", - "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", - "dev": true, - "optional": true, - "requires": { - "micromatch": "^3.1.4", - "normalize-path": "^2.1.1" - }, - "dependencies": { - "normalize-path": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", - "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", - "dev": true, - "optional": true, - "requires": { - "remove-trailing-separator": "^1.0.1" - } - } - } - }, - "append-transform": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz", - "integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==", - "dev": true, - "requires": { - "default-require-extensions": "^3.0.0" - } - }, - "archy": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", - "integrity": "sha1-+cjBN1fMHde8N5rHeyxipcKGjEA=", - "dev": true - }, - "arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true - }, - "argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "requires": { - "sprintf-js": "~1.0.2" - } - }, - "argv": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/argv/-/argv-0.0.2.tgz", - "integrity": "sha1-7L0W+JSbFXGDcRsb2jNPN4QBhas=", - "dev": true - }, - "arr-diff": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz", - "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA=", - "dev": true, - "optional": true - }, - "arr-flatten": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz", - "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==", - "dev": true, - "optional": true - }, - "arr-union": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz", - "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ=", - "dev": true, - "optional": true - }, - "array-unique": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz", - "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg=", - "dev": true, - "optional": true - }, - "assertion-error": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz", - "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==", - "dev": true - }, - "assign-symbols": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz", - "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c=", - "dev": true, - "optional": true - }, - "async-each": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz", - "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==", - "dev": true, - "optional": true - }, - "atob": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz", - "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==", - "dev": true, - "optional": true - }, - "babel-code-frame": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-code-frame/-/babel-code-frame-6.26.0.tgz", - "integrity": "sha1-Y/1D99weO7fONZR9uP42mj9Yx0s=", - "dev": true, - "requires": { - "chalk": "^1.1.3", - "esutils": "^2.0.2", - "js-tokens": "^3.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - }, - "ansi-styles": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz", - "integrity": "sha1-tDLdM1i2NM914eRmQ2gkBTPB3b4=", - "dev": true - }, - "chalk": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz", - "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", - "dev": true, - "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" - } - }, - "js-tokens": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.2.tgz", - "integrity": "sha1-mGbfOVECEw449/mWvOtlRDIJwls=", - "dev": true - }, - "strip-ansi": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", - "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - } - }, - "supports-color": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz", - "integrity": "sha1-U10EXOa2Nj+kARcIRimZXp3zJMc=", - "dev": true - } - } - }, - "babel-helper-function-name": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-function-name/-/babel-helper-function-name-6.24.1.tgz", - "integrity": "sha1-00dbjAPtmCQqJbSDUasYOZ01gKk=", - "dev": true, - "requires": { - "babel-helper-get-function-arity": "^6.24.1", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1", - "babel-traverse": "^6.24.1", - "babel-types": "^6.24.1" - } - }, - "babel-helper-get-function-arity": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-helper-get-function-arity/-/babel-helper-get-function-arity-6.24.1.tgz", - "integrity": "sha1-j3eCqpNAfEHTqlCQj4mwMbG2hT0=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0", - "babel-types": "^6.24.1" - } - }, - "babel-messages": { - "version": "6.23.0", - "resolved": "https://registry.npmjs.org/babel-messages/-/babel-messages-6.23.0.tgz", - "integrity": "sha1-8830cDhYA1sqKVHG7F7fbGLyYw4=", - "dev": true, - "requires": { - "babel-runtime": "^6.22.0" - } - }, - "babel-plugin-dynamic-import-node": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz", - "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==", - "dev": true, - "requires": { - "object.assign": "^4.1.0" - } - }, - "babel-plugin-syntax-class-properties": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/babel-plugin-syntax-class-properties/-/babel-plugin-syntax-class-properties-6.13.0.tgz", - "integrity": "sha1-1+sjt5oxf4VDlixQW4J8fWysJ94=", - "dev": true - }, - "babel-plugin-transform-class-properties": { - "version": "6.24.1", - "resolved": "https://registry.npmjs.org/babel-plugin-transform-class-properties/-/babel-plugin-transform-class-properties-6.24.1.tgz", - "integrity": "sha1-anl2PqYdM9NvN7YRqp3vgagbRqw=", - "dev": true, - "requires": { - "babel-helper-function-name": "^6.24.1", - "babel-plugin-syntax-class-properties": "^6.8.0", - "babel-runtime": "^6.22.0", - "babel-template": "^6.24.1" - } - }, - "babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", - "dev": true, - "requires": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" - }, - "dependencies": { - "regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", - "dev": true - } - } - }, - "babel-template": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-template/-/babel-template-6.26.0.tgz", - "integrity": "sha1-3gPi0WOWsGn0bdn/+FIfsaDjXgI=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "babel-traverse": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "lodash": "^4.17.4" - } - }, - "babel-traverse": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-traverse/-/babel-traverse-6.26.0.tgz", - "integrity": "sha1-RqnL1+3MYsjlwGTi0tjQ9ANXZu4=", - "dev": true, - "requires": { - "babel-code-frame": "^6.26.0", - "babel-messages": "^6.23.0", - "babel-runtime": "^6.26.0", - "babel-types": "^6.26.0", - "babylon": "^6.18.0", - "debug": "^2.6.8", - "globals": "^9.18.0", - "invariant": "^2.2.2", - "lodash": "^4.17.4" - }, - "dependencies": { - "globals": { - "version": "9.18.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-9.18.0.tgz", - "integrity": "sha512-S0nG3CLEQiY/ILxqtztTWH/3iRRdyBLw6KMDxnKMchrtbj2OFmehVh0WUCfW3DUrIgx/qFrJPICrq4Z4sTR9UQ==", - "dev": true - } - } - }, - "babel-types": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz", - "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=", - "dev": true, - "requires": { - "babel-runtime": "^6.26.0", - "esutils": "^2.0.2", - "lodash": "^4.17.4", - "to-fast-properties": "^1.0.3" - }, - "dependencies": { - "to-fast-properties": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz", - "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc=", - "dev": true - } - } - }, - "babylon": { - "version": "6.18.0", - "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz", - "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ==", - "dev": true - }, - "balanced-match": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", - "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=", - "dev": true - }, - "base": { - "version": "0.11.2", - "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz", - "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==", - "dev": true, - "optional": true, - "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "optional": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "binary-extensions": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", - "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", - "dev": true, - "optional": true - }, - "bindings": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", - "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==", - "dev": true, - "optional": true, - "requires": { - "file-uri-to-path": "1.0.0" - } - }, - "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "requires": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "braces": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", - "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", - "dev": true, - "optional": true, - "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "browserslist": { - "version": "4.16.6", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz", - "integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==", - "dev": true, - "requires": { - "caniuse-lite": "^1.0.30001219", - "colorette": "^1.2.2", - "electron-to-chromium": "^1.3.723", - "escalade": "^3.1.1", - "node-releases": "^1.1.71" - }, - "dependencies": { - "electron-to-chromium": { - "version": "1.3.776", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.776.tgz", - "integrity": "sha512-V0w7eFSBoFPpdw4xexjVPZ770UDZIevSwkkj4W97XbE3IsCsTRFpa7/yXGZ88EOQAUEA09JMMsWK0xsw0kRAYw==", - "dev": true - }, - "node-releases": { - "version": "1.1.73", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz", - "integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==", - "dev": true - } - } - }, - "buffer-from": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz", - "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A==", - "dev": true - }, - "builtin-modules": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.2.0.tgz", - "integrity": "sha512-lGzLKcioL90C7wMczpkY0n/oART3MbBa8R9OFGE1rJxoVI86u4WAGfEk8Wjv10eKSyTHVGkSo3bvBylCEtk7LA==", - "dev": true - }, - "cache-base": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz", - "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==", - "dev": true, - "optional": true, - "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" - } - }, - "caching-transform": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz", - "integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==", - "dev": true, - "requires": { - "hasha": "^5.0.0", - "make-dir": "^3.0.0", - "package-hash": "^4.0.0", - "write-file-atomic": "^3.0.0" - }, - "dependencies": { - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", - "dev": true - }, - "caniuse-lite": { - "version": "1.0.30001232", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001232.tgz", - "integrity": "sha512-e4Gyp7P8vqC2qV2iHA+cJNf/yqUKOShXQOJHQt81OHxlIZl/j/j3soEA0adAQi8CPUQgvOdDENyQ5kd6a6mNSg==", - "dev": true - }, - "chai": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz", - "integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==", - "dev": true, - "requires": { - "assertion-error": "^1.1.0", - "check-error": "^1.0.2", - "deep-eql": "^3.0.1", - "get-func-name": "^2.0.0", - "pathval": "^1.1.0", - "type-detect": "^4.0.5" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "check-error": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz", - "integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII=", - "dev": true - }, - "chokidar": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz", - "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==", - "dev": true, - "optional": true, - "requires": { - "anymatch": "^2.0.0", - "async-each": "^1.0.1", - "braces": "^2.3.2", - "fsevents": "^1.2.7", - "glob-parent": "^3.1.0", - "inherits": "^2.0.3", - "is-binary-path": "^1.0.0", - "is-glob": "^4.0.0", - "normalize-path": "^3.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.2.1", - "upath": "^1.1.1" - } - }, - "class-utils": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz", - "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==", - "dev": true, - "optional": true, - "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "dev": true - }, - "cliui": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz", - "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==", - "dev": true, - "requires": { - "string-width": "^3.1.0", - "strip-ansi": "^5.2.0", - "wrap-ansi": "^5.1.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "clone-deep": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", - "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", - "dev": true, - "requires": { - "is-plain-object": "^2.0.4", - "kind-of": "^6.0.2", - "shallow-clone": "^3.0.0" - } - }, - "codecov": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/codecov/-/codecov-3.8.0.tgz", - "integrity": "sha512-7E/S7hmq2CJvCMBMu+aRACO9jxQX1HJug/M3ub8+t84R+5Ai2T5sFMxS3W8P41m2A63+VSAAL4U0aBlqZXkJPw==", - "dev": true, - "requires": { - "argv": "0.0.2", - "ignore-walk": "3.0.3", - "js-yaml": "3.14.0", - "teeny-request": "7.0.1", - "urlgrey": "0.4.4" - } - }, - "collection-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz", - "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", - "dev": true, - "optional": true, - "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", - "dev": true - }, - "colorette": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz", - "integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==", - "dev": true - }, - "commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true - }, - "commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=", - "dev": true - }, - "component-emitter": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz", - "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==", - "dev": true, - "optional": true - }, - "concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", - "dev": true - }, - "convert-source-map": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.7.0.tgz", - "integrity": "sha512-4FJkXzKXEDB1snCFZlLP4gpC3JILicCpGbzG9f9G7tGqGCzETQ2hWPrcinA9oU4wtf2biUaEH5065UnMeR33oA==", - "dev": true, - "requires": { - "safe-buffer": "~5.1.1" - } - }, - "copy-descriptor": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", - "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40=", - "dev": true, - "optional": true - }, - "core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "dev": true - }, - "core-js-compat": { - "version": "3.6.5", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.6.5.tgz", - "integrity": "sha512-7ItTKOhOZbznhXAQ2g/slGg1PJV5zDO/WdkTwi7UEOJmkvsE32PWvx6mKtDjiMpjnR2CNf6BAD6sSxIlv7ptng==", - "dev": true, - "requires": { - "browserslist": "^4.8.5", - "semver": "7.0.0" - }, - "dependencies": { - "semver": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz", - "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==", - "dev": true - } - } - }, - "core-util-is": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", - "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=", - "dev": true, - "optional": true - }, - "create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true - }, - "cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", - "dev": true, - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "dependencies": { - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "debug": { - "version": "2.6.9", - "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", - "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", - "dev": true, - "requires": { - "ms": "2.0.0" - } - }, - "decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", - "dev": true - }, - "decode-uri-component": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz", - "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", - "dev": true, - "optional": true - }, - "deep-eql": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz", - "integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==", - "dev": true, - "requires": { - "type-detect": "^4.0.0" - } - }, - "deep-freeze": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz", - "integrity": "sha1-OgsABd4YZygZ39OM0x+RF5yJPoQ=", - "dev": true - }, - "deepmerge": { - "version": "4.2.2", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz", - "integrity": "sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==", - "dev": true - }, - "default-require-extensions": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.0.tgz", - "integrity": "sha512-ek6DpXq/SCpvjhpFsLFRVtIxJCRw6fUR42lYMVZuUMK7n8eMz4Uh5clckdBjEpLhn/gEBZo7hDJnJcwdKLKQjg==", - "dev": true, - "requires": { - "strip-bom": "^4.0.0" - } - }, - "define-properties": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", - "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, - "requires": { - "object-keys": "^1.0.12" - } - }, - "define-property": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz", - "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" - }, - "dependencies": { - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "optional": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "diff": { - "version": "3.5.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz", - "integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==", - "dev": true - }, - "emoji-regex": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz", - "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==", - "dev": true - }, - "es-abstract": { - "version": "1.18.0-next.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.1.tgz", - "integrity": "sha512-I4UGspA0wpZXWENrdA0uHbnhte683t3qT/1VFH9aX2dA5PPSf6QW5HHXf5HImaqPmjXaVeVk4RGWnaylmV7uAA==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-negative-zero": "^2.0.0", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - }, - "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, - "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" - } - }, - "es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true - }, - "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", - "dev": true - }, - "esm": { - "version": "3.2.25", - "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", - "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", - "dev": true - }, - "esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true - }, - "estree-walker": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", - "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", - "dev": true - }, - "esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true - }, - "expand-brackets": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz", - "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", - "dev": true, - "optional": true, - "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "extend-shallow": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz", - "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", - "dev": true, - "optional": true, - "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "optional": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "extglob": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz", - "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==", - "dev": true, - "optional": true, - "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "optional": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "file-uri-to-path": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz", - "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", - "dev": true, - "optional": true - }, - "fill-range": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", - "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", - "dev": true, - "optional": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "find-cache-dir": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.1.tgz", - "integrity": "sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==", - "dev": true, - "requires": { - "commondir": "^1.0.1", - "make-dir": "^3.0.2", - "pkg-dir": "^4.1.0" - }, - "dependencies": { - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "find-up": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", - "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", - "dev": true, - "requires": { - "locate-path": "^3.0.0" - } - }, - "flat": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/flat/-/flat-4.1.0.tgz", - "integrity": "sha512-Px/TiLIznH7gEDlPXcUD4KnBusa6kR6ayRUVcnEAbreRIuhkqow/mun59BuRXwoYk7ZQOLW1ZM05ilIvK38hFw==", - "dev": true, - "requires": { - "is-buffer": "~2.0.3" - }, - "dependencies": { - "is-buffer": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.4.tgz", - "integrity": "sha512-Kq1rokWXOPXWuaMAqZiJW4XxsmD9zGx9q4aePabbn3qCRGedtH7Cm+zV8WETitMfu1wdh+Rvd6w5egwSngUX2A==", - "dev": true - } - } - }, - "for-in": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz", - "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA=", - "dev": true, - "optional": true - }, - "foreground-child": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz", - "integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==", - "dev": true, - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^3.0.2" - } - }, - "formdata-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-2.1.0.tgz", - "integrity": "sha512-CnnnN2OICKs+qyybHU2bAobkj8OSeRJD/mSqkzbMHtTVDF0WMhbi/VtuKCQF4LHCqSKqENFzrs3rwKNW2dm2lQ==", - "dev": true, - "requires": { - "@babel/runtime": "7.7.7", - "mime-types": "2.1.25", - "nanoid": "2.1.8" - }, - "dependencies": { - "@babel/runtime": { - "version": "7.7.7", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.7.7.tgz", - "integrity": "sha512-uCnC2JEVAu8AKB5do1WRIsvrdJ0flYx/A/9f/6chdacnEZ7LmavjdsDXr5ksYBegxtuTPR5Va9/+13QF/kFkCA==", - "dev": true, - "requires": { - "regenerator-runtime": "^0.13.2" - } - } - } - }, - "fragment-cache": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz", - "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", - "dev": true, - "optional": true, - "requires": { - "map-cache": "^0.2.2" - } - }, - "fromentries": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.2.1.tgz", - "integrity": "sha512-Xu2Qh8yqYuDhQGOhD5iJGninErSfI9A3FrriD3tjUgV5VbJFeH8vfgZ9HnC6jWN80QDVNQK5vmxRAmEAp7Mevw==", - "dev": true - }, - "fs-readdir-recursive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", - "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", - "dev": true - }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true - }, - "fsevents": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz", - "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==", - "dev": true, - "optional": true, - "requires": { - "bindings": "^1.5.0", - "nan": "^2.12.1" - } - }, - "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, - "gensync": { - "version": "1.0.0-beta.1", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.1.tgz", - "integrity": "sha512-r8EC6NO1sngH/zdD9fiRDLdcgnbayXah+mLgManTaIZJqEC1MZstmnox8KpnI2/fxQwrp5OpCOYWLp4rBl4Jcg==", - "dev": true - }, - "get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true - }, - "get-func-name": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz", - "integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE=", - "dev": true - }, - "get-package-type": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", - "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", - "dev": true - }, - "get-value": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", - "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg=", - "dev": true, - "optional": true - }, - "glob": { - "version": "7.1.6", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", - "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz", - "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", - "dev": true, - "optional": true, - "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" - }, - "dependencies": { - "is-glob": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", - "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", - "dev": true, - "optional": true, - "requires": { - "is-extglob": "^2.1.0" - } - } - } - }, - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - }, - "graceful-fs": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.4.tgz", - "integrity": "sha512-WjKPNJF79dtJAVniUlGGWHYGz2jWxT6VhN/4m1NdkbZ2nOsEF+cI1Edgql5zCRhs/VsQYRvrXctxktVXZUkixw==", - "dev": true - }, - "growl": { - "version": "1.10.5", - "resolved": "https://registry.npmjs.org/growl/-/growl-1.10.5.tgz", - "integrity": "sha512-qBr4OuELkhPenW6goKVXiv47US3clb3/IbuWF9KNKEijAy9oeHxU9IgzjvJhHkUzhaj7rOUD7+YGWqUjLp5oSA==", - "dev": true - }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, - "has-ansi": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz", - "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", - "dev": true, - "requires": { - "ansi-regex": "^2.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", - "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=", - "dev": true - } - } - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", - "dev": true - }, - "has-symbols": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true - }, - "has-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz", - "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", - "dev": true, - "optional": true, - "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" - } - }, - "has-values": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz", - "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", - "dev": true, - "optional": true, - "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" - }, - "dependencies": { - "kind-of": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz", - "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "hasha": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", - "integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==", - "dev": true, - "requires": { - "is-stream": "^2.0.0", - "type-fest": "^0.8.0" - } - }, - "he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true - }, - "html-escaper": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", - "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", - "dev": true - }, - "http-proxy-agent": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", - "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==", - "dev": true, - "requires": { - "@tootallnate/once": "1", - "agent-base": "6", - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "https-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.0.tgz", - "integrity": "sha512-EkYm5BcKUGiduxzSt3Eppko+PiNWNEpa4ySk9vTC6wDsQJW9rHSa+UhGNJoRYp7bz6Ht1eaRIa6QaJqO5rCFbA==", - "dev": true, - "requires": { - "agent-base": "6", - "debug": "4" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, - "ignore-walk": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.3.tgz", - "integrity": "sha512-m7o6xuOaT1aqheYHKf8W6J5pYH85ZI9w077erOzLje3JsB1gkafkAhHHY19dqjulgIZHFm32Cp5uNZgcQqdJKw==", - "dev": true, - "requires": { - "minimatch": "^3.0.4" - } - }, - "imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", - "dev": true - }, - "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "dev": true - }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, - "invariant": { - "version": "2.2.4", - "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", - "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, - "requires": { - "loose-envify": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz", - "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-binary-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", - "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", - "dev": true, - "optional": true, - "requires": { - "binary-extensions": "^1.0.0" - } - }, - "is-buffer": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", - "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", - "dev": true, - "optional": true - }, - "is-callable": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.2.tgz", - "integrity": "sha512-dnMqspv5nU3LoewK2N/y7KLtxtakvTuaCsU9FU50/QDmdbHNy/4/JuRtMHqRU22o3q+W89YQndQEeCVwK+3qrA==", - "dev": true - }, - "is-data-descriptor": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz", - "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-date-object": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true - }, - "is-descriptor": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz", - "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==", - "dev": true, - "optional": true, - "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" - }, - "dependencies": { - "kind-of": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz", - "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==", - "dev": true, - "optional": true - } - } - }, - "is-extendable": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz", - "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=", - "dev": true, - "optional": true - }, - "is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", - "dev": true - }, - "is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", - "dev": true - }, - "is-glob": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", - "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", - "dev": true, - "requires": { - "is-extglob": "^2.1.1" - } - }, - "is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=", - "dev": true - }, - "is-negative-zero": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", - "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", - "dev": true - }, - "is-number": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", - "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "is-plain-object": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", - "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", - "dev": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "is-reference": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", - "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", - "dev": true, - "requires": { - "@types/estree": "*" - } - }, - "is-regex": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.1.tgz", - "integrity": "sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.0.tgz", - "integrity": "sha512-XCoy+WlUr7d1+Z8GgSuXmpuUFC9fOhRXglJMx+dwLKTkL44Cjd4W1Z5P+BQZpr+cR93aGP4S/s7Ftw6Nd/kiEw==", - "dev": true - }, - "is-symbol": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", - "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, - "requires": { - "has-symbols": "^1.0.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=", - "dev": true - }, - "is-windows": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", - "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", - "dev": true - }, - "isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", - "dev": true, - "optional": true - }, - "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", - "dev": true - }, - "isobject": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", - "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", - "dev": true - }, - "istanbul-lib-coverage": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.0.0.tgz", - "integrity": "sha512-UiUIqxMgRDET6eR+o5HbfRYP1l0hqkWOs7vNxC/mggutCMUIhWMm8gAHb8tHlyfD3/l6rlgNA5cKdDzEAf6hEg==", - "dev": true - }, - "istanbul-lib-hook": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz", - "integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==", - "dev": true, - "requires": { - "append-transform": "^2.0.0" - } - }, - "istanbul-lib-instrument": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz", - "integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==", - "dev": true, - "requires": { - "@babel/core": "^7.7.5", - "@istanbuljs/schema": "^0.1.2", - "istanbul-lib-coverage": "^3.0.0", - "semver": "^6.3.0" - }, - "dependencies": { - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - } - } - }, - "istanbul-lib-processinfo": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.2.tgz", - "integrity": "sha512-kOwpa7z9hme+IBPZMzQ5vdQj8srYgAtaRqeI48NGmAQ+/5yKiHLV0QbYqQpxsdEF0+w14SoB8YbnHKcXE2KnYw==", - "dev": true, - "requires": { - "archy": "^1.0.0", - "cross-spawn": "^7.0.0", - "istanbul-lib-coverage": "^3.0.0-alpha.1", - "make-dir": "^3.0.0", - "p-map": "^3.0.0", - "rimraf": "^3.0.0", - "uuid": "^3.3.3" - }, - "dependencies": { - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "uuid": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", - "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", - "dev": true - } - } - }, - "istanbul-lib-report": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz", - "integrity": "sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw==", - "dev": true, - "requires": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^3.0.0", - "supports-color": "^7.1.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "istanbul-lib-source-maps": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.0.tgz", - "integrity": "sha512-c16LpFRkR8vQXyHZ5nLpY35JZtzj1PQY1iZmesUbf1FZHbIupcWfjgOXBY9YHkLEQ6puz1u4Dgj6qmU/DisrZg==", - "dev": true, - "requires": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" - }, - "dependencies": { - "debug": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.2.0.tgz", - "integrity": "sha512-IX2ncY78vDTjZMFUdmsvIRFY2Cf4FnD0wRs+nQwJU8Lu99/tPFdb0VybiiMTPe3I6rQmwsqQqRBvxU+bZ/I8sg==", - "dev": true, - "requires": { - "ms": "2.1.2" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "istanbul-reports": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.0.2.tgz", - "integrity": "sha512-9tZvz7AiR3PEDNGiV9vIouQ/EAcqMXFmkcA1CDFTwOB98OZVDL0PH9glHotf5Ugp6GCOTypfzGWI/OqjWNCRUw==", - "dev": true, - "requires": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" - } - }, - "jest-worker": { - "version": "26.5.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.5.0.tgz", - "integrity": "sha512-kTw66Dn4ZX7WpjZ7T/SUDgRhapFRKWmisVAF0Rv4Fu8SLFD7eLbqpLvbxVqYhSgaWa7I+bW7pHnbyfNsH6stug==", - "dev": true, - "requires": { - "@types/node": "*", - "merge-stream": "^2.0.0", - "supports-color": "^7.0.0" - }, - "dependencies": { - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "js-cleanup": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/js-cleanup/-/js-cleanup-1.2.0.tgz", - "integrity": "sha512-JeDD0yiiSt80fXzAVa/crrS0JDPQljyBG/RpOtaSbyDq03VHa9szJWMaWOYU/bcTn412uMN2MxApXq8v79cUiQ==", - "dev": true, - "requires": { - "magic-string": "^0.25.7", - "perf-regexes": "^1.0.1", - "skip-regex": "^1.0.2" - } - }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, - "js-yaml": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.0.tgz", - "integrity": "sha512-/4IbIeHcD9VMHFqDR/gQ7EdZdLimOvW2DdcxFjdyyZ9NsbS+ccrXqVWDtab/lRl5AlUqmpBx8EhPaWR+OtY17A==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "jsesc": { - "version": "2.5.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", - "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", - "dev": true - }, - "json5": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz", - "integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "just-extend": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-4.1.1.tgz", - "integrity": "sha512-aWgeGFW67BP3e5181Ep1Fv2v8z//iBJfrvyTnq8wG86vEESwmonn1zPBJ0VfmT9CJq2FIT0VsETtrNFm2a+SHA==", - "dev": true - }, - "kind-of": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", - "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", - "dev": true - }, - "leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", - "dev": true - }, - "levenary": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/levenary/-/levenary-1.1.1.tgz", - "integrity": "sha512-mkAdOIt79FD6irqjYSs4rdbnlT5vRonMEvBVPVb3XmevfS8kgRXwfes0dhPdEtzTWD/1eNE/Bm/G1iRt6DcnQQ==", - "dev": true, - "requires": { - "leven": "^3.1.0" - } - }, - "locate-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", - "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", - "dev": true, - "requires": { - "p-locate": "^3.0.0", - "path-exists": "^3.0.0" - } - }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, - "lodash.flattendeep": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz", - "integrity": "sha1-+wMJF/hqMTTlvJvsDWngAT3f7bI=", - "dev": true - }, - "lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", - "dev": true - }, - "log-symbols": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-3.0.0.tgz", - "integrity": "sha512-dSkNGuI7iG3mfvDzUuYZyvk5dD9ocYCYzNU6CYDE6+Xqd+gwme6Z00NS3dUh8mq/73HaEtT7m6W+yUPtU6BZnQ==", - "dev": true, - "requires": { - "chalk": "^2.4.2" - } - }, - "lolex": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/lolex/-/lolex-5.1.2.tgz", - "integrity": "sha512-h4hmjAvHTmd+25JSwrtTIuwbKdwg5NzZVRMLn9saij4SZaepCrTCxPr35H/3bjwfMJtN+t3CX8672UIkglz28A==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0" - } - }, - "loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, - "requires": { - "js-tokens": "^3.0.0 || ^4.0.0" - } - }, - "magic-string": { - "version": "0.25.7", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.7.tgz", - "integrity": "sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==", - "dev": true, - "requires": { - "sourcemap-codec": "^1.4.4" - } - }, - "make-dir": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", - "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", - "dev": true, - "requires": { - "pify": "^4.0.1", - "semver": "^5.6.0" - } - }, - "make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true - }, - "map-cache": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", - "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8=", - "dev": true, - "optional": true - }, - "map-visit": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz", - "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", - "dev": true, - "optional": true, - "requires": { - "object-visit": "^1.0.0" - } - }, - "merge-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", - "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", - "dev": true - }, - "micromatch": { - "version": "3.1.10", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", - "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", - "dev": true, - "optional": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" - } - }, - "mime-db": { - "version": "1.42.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", - "integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==", - "dev": true - }, - "mime-types": { - "version": "2.1.25", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", - "integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", - "dev": true, - "requires": { - "mime-db": "1.42.0" - } - }, - "minimatch": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", - "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", - "dev": true, - "requires": { - "brace-expansion": "^1.1.7" - } - }, - "minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", - "dev": true - }, - "mixin-deep": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz", - "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==", - "dev": true, - "optional": true, - "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" - }, - "dependencies": { - "is-extendable": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz", - "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==", - "dev": true, - "optional": true, - "requires": { - "is-plain-object": "^2.0.4" - } - } - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "mocha": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz", - "integrity": "sha512-O9CIypScywTVpNaRrCAgoUnJgozpIofjKUYmJhiCIJMiuYnLI6otcb1/kpW9/n/tJODHGZ7i8aLQoDVsMtOKQQ==", - "dev": true, - "requires": { - "ansi-colors": "3.2.3", - "browser-stdout": "1.3.1", - "chokidar": "3.3.0", - "debug": "3.2.6", - "diff": "3.5.0", - "escape-string-regexp": "1.0.5", - "find-up": "3.0.0", - "glob": "7.1.3", - "growl": "1.10.5", - "he": "1.2.0", - "js-yaml": "3.13.1", - "log-symbols": "3.0.0", - "minimatch": "3.0.4", - "mkdirp": "0.5.5", - "ms": "2.1.1", - "node-environment-flags": "1.0.6", - "object.assign": "4.1.0", - "strip-json-comments": "2.0.1", - "supports-color": "6.0.0", - "which": "1.3.1", - "wide-align": "1.1.3", - "yargs": "13.3.2", - "yargs-parser": "13.1.2", - "yargs-unparser": "1.6.0" - }, - "dependencies": { - "anymatch": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.1.tgz", - "integrity": "sha512-mM8522psRCqzV+6LhomX5wgp25YVibjh8Wj23I5RPkPppSVSjyKD2A2mBJmWGa+KN7f2D6LNh9jkBCeyLktzjg==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, - "binary-extensions": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.1.0.tgz", - "integrity": "sha512-1Yj8h9Q+QDF5FzhMs/c9+6UntbD5MkRfRwac8DoEm9ZfUBZ7tZ55YcGVAzEe4bXsdQHEk+s9S5wsOKVdZrw0tQ==", - "dev": true - }, - "braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", - "dev": true, - "requires": { - "fill-range": "^7.0.1" - } - }, - "chokidar": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.3.0.tgz", - "integrity": "sha512-dGmKLDdT3Gdl7fBUe8XK+gAtGmzy5Fn0XkkWQuYxGIgWVPPse2CxFA5mtrlD0TOHaHjEUqkWNyP1XdHoJES/4A==", - "dev": true, - "requires": { - "anymatch": "~3.1.1", - "braces": "~3.0.2", - "fsevents": "~2.1.1", - "glob-parent": "~5.1.0", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.2.0" - } - }, - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", - "dev": true, - "requires": { - "to-regex-range": "^5.0.1" - } - }, - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true - }, - "glob": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", - "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - }, - "glob-parent": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz", - "integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "requires": { - "binary-extensions": "^2.0.0" - } - }, - "is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true - }, - "js-yaml": { - "version": "3.13.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz", - "integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==", - "dev": true, - "requires": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - } - }, - "ms": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", - "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", - "dev": true - }, - "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, - "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" - } - }, - "readdirp": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.2.0.tgz", - "integrity": "sha512-crk4Qu3pmXwgxdSgGhgA/eXiJAPQiX4GMOZZMXnqKxHX7TaoL+3gQVo/WeuAiogr07DpnfjIMpXXa+PAIvwPGQ==", - "dev": true, - "requires": { - "picomatch": "^2.0.4" - } - }, - "supports-color": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.0.0.tgz", - "integrity": "sha512-on9Kwidc1IUQo+bQdhi8+Tijpo0e1SS6RoGo2guUwn5vdaxw8RXOF9Vb2ws+ihWOmh4JnCJOvaziZWP1VABaLg==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "requires": { - "is-number": "^7.0.0" - } - } - } - }, - "ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", - "dev": true - }, - "nan": { - "version": "2.14.1", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.1.tgz", - "integrity": "sha512-isWHgVjnFjh2x2yuJ/tj3JbwoHu3UC2dX5G/88Cm24yB6YopVgxvBObDY7n5xW6ExmFhJpSEQqFPvq9zaXc8Jw==", - "dev": true, - "optional": true - }, - "nanoid": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.8.tgz", - "integrity": "sha512-g1z+n5s26w0TGKh7gjn7HCqurNKMZWzH08elXzh/gM/csQHd/UqDV6uxMghQYg9IvqRPm1QpeMk50YMofHvEjQ==", - "dev": true - }, - "nanomatch": { - "version": "1.2.13", - "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz", - "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==", - "dev": true, - "optional": true, - "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" - } - }, - "nise": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/nise/-/nise-3.0.1.tgz", - "integrity": "sha512-fYcH9y0drBGSoi88kvhpbZEsenX58Yr+wOJ4/Mi1K4cy+iGP/a73gNoyNhu5E9QxPdgTlVChfIaAlnyOy/gHUA==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/formatio": "^4.0.1", - "@sinonjs/text-encoding": "^0.7.1", - "just-extend": "^4.0.2", - "lolex": "^5.0.1", - "path-to-regexp": "^1.7.0" - } - }, - "node-environment-flags": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/node-environment-flags/-/node-environment-flags-1.0.6.tgz", - "integrity": "sha512-5Evy2epuL+6TM0lCQGpFIj6KwiEsGh1SrHUhTbNX+sLbBtjidPZFAnVK9y5yU1+h//RitLbRHTIMyxQPtxMdHw==", - "dev": true, - "requires": { - "object.getownpropertydescriptors": "^2.0.3", - "semver": "^5.7.0" - } - }, - "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", - "dev": true, - "requires": { - "whatwg-url": "^5.0.0" - } - }, - "node-modules-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/node-modules-regexp/-/node-modules-regexp-1.0.0.tgz", - "integrity": "sha1-jZ2+KJZKSsVxLpExZCEHxx6Q7EA=", - "dev": true - }, - "node-preload": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz", - "integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==", - "dev": true, - "requires": { - "process-on-spawn": "^1.0.0" - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true - }, - "nyc": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz", - "integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==", - "dev": true, - "requires": { - "@istanbuljs/load-nyc-config": "^1.0.0", - "@istanbuljs/schema": "^0.1.2", - "caching-transform": "^4.0.0", - "convert-source-map": "^1.7.0", - "decamelize": "^1.2.0", - "find-cache-dir": "^3.2.0", - "find-up": "^4.1.0", - "foreground-child": "^2.0.0", - "get-package-type": "^0.1.0", - "glob": "^7.1.6", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-hook": "^3.0.0", - "istanbul-lib-instrument": "^4.0.0", - "istanbul-lib-processinfo": "^2.0.2", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.0.2", - "make-dir": "^3.0.0", - "node-preload": "^0.2.1", - "p-map": "^3.0.0", - "process-on-spawn": "^1.0.0", - "resolve-from": "^5.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "spawn-wrap": "^2.0.0", - "test-exclude": "^6.0.0", - "yargs": "^15.0.2" - }, - "dependencies": { - "ansi-regex": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz", - "integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg==", - "dev": true - }, - "ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "requires": { - "color-convert": "^2.0.1" - } - }, - "cliui": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", - "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", - "dev": true, - "requires": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^6.2.0" - } - }, - "color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "requires": { - "color-name": "~1.1.4" - } - }, - "color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true - }, - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "string-width": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz", - "integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==", - "dev": true, - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.0" - } - }, - "strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", - "dev": true, - "requires": { - "ansi-regex": "^5.0.0" - } - }, - "wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, - "yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, - "requires": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" - } - }, - "yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - } - } - }, - "object-copy": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz", - "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", - "dev": true, - "optional": true, - "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "object-inspect": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.8.0.tgz", - "integrity": "sha512-jLdtEOB112fORuypAyl/50VRVIBIdVQOSUUGQHzJ4xBSbit81zRarz7GThkEFZy1RceYrWYcPcBFPQwHyAc1gA==", - "dev": true - }, - "object-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true - }, - "object-visit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", - "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", - "dev": true, - "optional": true, - "requires": { - "isobject": "^3.0.0" - } - }, - "object.assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", - "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.18.0-next.0", - "has-symbols": "^1.0.1", - "object-keys": "^1.1.1" - } - }, - "object.getownpropertydescriptors": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.0.tgz", - "integrity": "sha512-Z53Oah9A3TdLoblT7VKJaTDdXdT+lQO+cNpKVnya5JDe9uLvzu1YyY1yFDFrcxrlRgWrEFH0jJtD/IbuwjcEVg==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.0-next.1" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } - } - }, - "object.pick": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz", - "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", - "dev": true, - "optional": true, - "requires": { - "isobject": "^3.0.1" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", - "dev": true, - "requires": { - "wrappy": "1" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", - "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", - "dev": true, - "requires": { - "p-limit": "^2.0.0" - } - }, - "p-map": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", - "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", - "dev": true, - "requires": { - "aggregate-error": "^3.0.0" - } - }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, - "package-hash": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz", - "integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.15", - "hasha": "^5.0.0", - "lodash.flattendeep": "^4.4.0", - "release-zalgo": "^1.0.0" - } - }, - "pascalcase": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz", - "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ=", - "dev": true, - "optional": true - }, - "path-dirname": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz", - "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA=", - "dev": true, - "optional": true - }, - "path-exists": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", - "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", - "dev": true - }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", - "dev": true - }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true - }, - "path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true - }, - "path-to-regexp": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-1.8.0.tgz", - "integrity": "sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA==", - "dev": true, - "requires": { - "isarray": "0.0.1" - }, - "dependencies": { - "isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", - "dev": true - } - } - }, - "pathval": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.1.tgz", - "integrity": "sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==", - "dev": true - }, - "perf-regexes": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/perf-regexes/-/perf-regexes-1.0.1.tgz", - "integrity": "sha512-L7MXxUDtqr4PUaLFCDCXBfGV/6KLIuSEccizDI7JxT+c9x1G1v04BQ4+4oag84SHaCdrBgQAIs/Cqn+flwFPng==", - "dev": true - }, - "picomatch": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.2.tgz", - "integrity": "sha512-q0M/9eZHzmr0AulXyPwNfZjtwZ/RBZlbN3K3CErVrk50T2ASYI7Bye0EvekFY3IP1Nt2DHu0re+V2ZHIpMkuWg==", - "dev": true - }, - "pify": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", - "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", - "dev": true - }, - "pirates": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.1.tgz", - "integrity": "sha512-WuNqLTbMI3tmfef2TKxlQmAiLHKtFhlsCZnPIpuv2Ow0RDVO8lfy1Opf4NUzlMXLjPl+Men7AuVdX6TA+s+uGA==", - "dev": true, - "requires": { - "node-modules-regexp": "^1.0.0" - } - }, - "pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "requires": { - "find-up": "^4.0.0" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true - } - } - }, - "posix-character-classes": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", - "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs=", - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", - "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", - "dev": true, - "optional": true - }, - "process-on-spawn": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.0.0.tgz", - "integrity": "sha512-1WsPDsUSMmZH5LeMLegqkPDrsGgsWwk1Exipy2hvB0o/F0ASzbpIctSCcZIK1ykJvtTJULEH+20WOFjMvGnCTg==", - "dev": true, - "requires": { - "fromentries": "^1.2.0" - } - }, - "randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "requires": { - "safe-buffer": "^5.1.0" - } - }, - "readable-stream": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", - "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", - "dev": true, - "optional": true, - "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" - } - }, - "readdirp": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", - "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", - "dev": true, - "optional": true, - "requires": { - "graceful-fs": "^4.1.11", - "micromatch": "^3.1.10", - "readable-stream": "^2.0.2" - } - }, - "regenerate": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.1.tgz", - "integrity": "sha512-j2+C8+NtXQgEKWk49MMP5P/u2GhnahTtVkRIHr5R5lVRlbKvmQ+oS+A5aLKWp2ma5VkT8sh6v+v4hbH0YHR66A==", - "dev": true - }, - "regenerate-unicode-properties": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-8.2.0.tgz", - "integrity": "sha512-F9DjY1vKLo/tPePDycuH3dn9H1OTPIkVD9Kz4LODu+F2C75mgjAJ7x/gwy6ZcSNRAAkhNlJSOHRe8k3p+K9WhA==", - "dev": true, - "requires": { - "regenerate": "^1.4.0" - } - }, - "regenerator-runtime": { - "version": "0.13.9", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.9.tgz", - "integrity": "sha512-p3VT+cOEgxFsRRA9X4lkI1E+k2/CtnKtU4gcxyaCUreilL/vqI6CdZ3wxVUx3UOUg+gnUOQQcRI7BmSI656MYA==", - "dev": true - }, - "regenerator-transform": { - "version": "0.14.5", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz", - "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==", - "dev": true, - "requires": { - "@babel/runtime": "^7.8.4" - } - }, - "regex-not": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", - "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==", - "dev": true, - "optional": true, - "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" - } - }, - "regexpu-core": { - "version": "4.7.1", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.7.1.tgz", - "integrity": "sha512-ywH2VUraA44DZQuRKzARmw6S66mr48pQVva4LBeRhcOltJ6hExvWly5ZjFLYo67xbIxb6W1q4bAGtgfEl20zfQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.2.0", - "regjsgen": "^0.5.1", - "regjsparser": "^0.6.4", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.2.0" - } - }, - "regjsgen": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz", - "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==", - "dev": true - }, - "regjsparser": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.4.tgz", - "integrity": "sha512-64O87/dPDgfk8/RQqC4gkZoGyyWFIEUTTh80CU6CWuK5vkCGyekIx+oKcEIYtP/RAxSQltCZHCNu/mdd7fqlJw==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - } - } - }, - "release-zalgo": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz", - "integrity": "sha1-CXALflB0Mpc5Mw5TXFqQ+2eFFzA=", - "dev": true, - "requires": { - "es6-error": "^4.0.1" - } - }, - "remove-trailing-separator": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", - "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8=", - "dev": true, - "optional": true - }, - "repeat-element": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.3.tgz", - "integrity": "sha512-ahGq0ZnV5m5XtZLMb+vP76kcAM5nkLqk0lpqAuojSKGgQtn4eRi4ZZGm2olo2zKFH+sMsWaqOCW1dqAnOru72g==", - "dev": true, - "optional": true - }, - "repeat-string": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", - "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc=", - "dev": true, - "optional": true - }, - "require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", - "dev": true - }, - "require-main-filename": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", - "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true - }, - "resolve": { - "version": "1.17.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", - "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", - "dev": true, - "requires": { - "path-parse": "^1.0.6" - } - }, - "resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true - }, - "resolve-url": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz", - "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=", - "dev": true, - "optional": true - }, - "ret": { - "version": "0.1.15", - "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz", - "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==", - "dev": true, - "optional": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "rollup": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.29.0.tgz", - "integrity": "sha512-gtU0sjxMpsVlpuAf4QXienPmUAhd6Kc7owQ4f5lypoxBW18fw2UNYZ4NssLGsri6WhUZkE/Ts3EMRebN+gNLiQ==", - "dev": true, - "requires": { - "fsevents": "~2.1.2" - }, - "dependencies": { - "fsevents": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.1.3.tgz", - "integrity": "sha512-Auw9a4AxqWpa9GUfj370BMPzzyncfBABW8Mab7BGWBYDj4Isgq+cDKtx0i6u9jcX9pQDnswsaaOTgTmA5pEjuQ==", - "dev": true, - "optional": true - } - } - }, - "rollup-plugin-cleanup": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/rollup-plugin-cleanup/-/rollup-plugin-cleanup-3.2.1.tgz", - "integrity": "sha512-zuv8EhoO3TpnrU8MX8W7YxSbO4gmOR0ny06Lm3nkFfq0IVKdBUtHwhVzY1OAJyNCIAdLiyPnOrU0KnO0Fri1GQ==", - "dev": true, - "requires": { - "js-cleanup": "^1.2.0", - "rollup-pluginutils": "^2.8.2" - } - }, - "rollup-plugin-commonjs": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz", - "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==", - "dev": true, - "requires": { - "estree-walker": "^0.6.1", - "is-reference": "^1.1.2", - "magic-string": "^0.25.2", - "resolve": "^1.11.0", - "rollup-pluginutils": "^2.8.1" - }, - "dependencies": { - "estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - } - } - }, - "rollup-plugin-terser": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-6.1.0.tgz", - "integrity": "sha512-4fB3M9nuoWxrwm39habpd4hvrbrde2W2GG4zEGPQg1YITNkM3Tqur5jSuXlWNzbv/2aMLJ+dZJaySc3GCD8oDw==", - "dev": true, - "requires": { - "@babel/code-frame": "^7.8.3", - "jest-worker": "^26.0.0", - "serialize-javascript": "^3.0.0", - "terser": "^4.7.0" - } - }, - "rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "dev": true, - "requires": { - "estree-walker": "^0.6.1" - }, - "dependencies": { - "estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", - "dev": true - } - } - }, - "safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "dev": true - }, - "safe-regex": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz", - "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", - "dev": true, - "optional": true, - "requires": { - "ret": "~0.1.10" - } - }, - "semver": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", - "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", - "dev": true - }, - "serialize-javascript": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", - "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", - "dev": true, - "requires": { - "randombytes": "^2.1.0" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=", - "dev": true - }, - "set-value": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz", - "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==", - "dev": true, - "optional": true, - "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" - }, - "dependencies": { - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "shallow-clone": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", - "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", - "dev": true, - "requires": { - "kind-of": "^6.0.2" - } - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true - }, - "signal-exit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", - "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", - "dev": true - }, - "sinon": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-8.1.1.tgz", - "integrity": "sha512-E+tWr3acRdoe1nXbHMu86SSqA1WGM7Yw3jZRLvlCMnXwTHP8lgFFVn5BnKnF26uc5SfZ3D7pA9sN7S3Y2jG4Ew==", - "dev": true, - "requires": { - "@sinonjs/commons": "^1.7.0", - "@sinonjs/formatio": "^4.0.1", - "@sinonjs/samsam": "^4.2.2", - "diff": "^4.0.2", - "lolex": "^5.1.2", - "nise": "^3.0.1", - "supports-color": "^7.1.0" - }, - "dependencies": { - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - }, - "has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true - }, - "supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "requires": { - "has-flag": "^4.0.0" - } - } - } - }, - "skip-regex": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/skip-regex/-/skip-regex-1.0.2.tgz", - "integrity": "sha512-pEjMUbwJ5Pl/6Vn6FsamXHXItJXSRftcibixDmNCWbWhic0hzHrwkMZo0IZ7fMRH9KxcWDFSkzhccB4285PutA==", - "dev": true - }, - "slash": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", - "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", - "dev": true - }, - "snapdragon": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz", - "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==", - "dev": true, - "optional": true, - "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^0.1.0" - } - }, - "extend-shallow": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", - "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", - "dev": true, - "optional": true, - "requires": { - "is-extendable": "^0.1.0" - } - } - } - }, - "snapdragon-node": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz", - "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==", - "dev": true, - "optional": true, - "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" - }, - "dependencies": { - "define-property": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz", - "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^1.0.0" - } - }, - "is-accessor-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz", - "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-data-descriptor": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", - "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^6.0.0" - } - }, - "is-descriptor": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", - "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==", - "dev": true, - "optional": true, - "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" - } - } - } - }, - "snapdragon-util": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz", - "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.2.0" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "source-map": { - "version": "0.5.7", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", - "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w=", - "dev": true - }, - "source-map-resolve": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz", - "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==", - "dev": true, - "optional": true, - "requires": { - "atob": "^2.1.2", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" - } - }, - "source-map-support": { - "version": "0.5.19", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.19.tgz", - "integrity": "sha512-Wonm7zOCIJzBGQdB+thsPar0kYuCIzYvxZwlBa87yi/Mdjv7Tip2cyVbLj5o0cFPN4EVkuTwb3GDDyUx2DGnGw==", - "dev": true, - "requires": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" - }, - "dependencies": { - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "source-map-url": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.0.tgz", - "integrity": "sha1-PpNdfd1zYxuXZZlW1VEo6HtQhKM=", - "dev": true, - "optional": true - }, - "sourcemap-codec": { - "version": "1.4.8", - "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", - "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", - "dev": true - }, - "spawn-wrap": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz", - "integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==", - "dev": true, - "requires": { - "foreground-child": "^2.0.0", - "is-windows": "^1.0.2", - "make-dir": "^3.0.0", - "rimraf": "^3.0.0", - "signal-exit": "^3.0.2", - "which": "^2.0.1" - }, - "dependencies": { - "make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", - "dev": true, - "requires": { - "semver": "^6.0.0" - } - }, - "semver": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", - "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", - "dev": true - }, - "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - } - } - }, - "split-string": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz", - "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==", - "dev": true, - "optional": true, - "requires": { - "extend-shallow": "^3.0.0" - } - }, - "sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", - "dev": true - }, - "static-extend": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", - "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", - "dev": true, - "optional": true, - "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" - }, - "dependencies": { - "define-property": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz", - "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", - "dev": true, - "optional": true, - "requires": { - "is-descriptor": "^0.1.0" - } - } - } - }, - "stream-events": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/stream-events/-/stream-events-1.0.5.tgz", - "integrity": "sha512-E1GUzBSgvct8Jsb3v2X15pjzN1tYebtbLaMg+eBOUOAxgbLoSbT2NS91ckc5lJD1KfLjId+jXJRgo0qnV5Nerg==", - "dev": true, - "requires": { - "stubs": "^3.0.0" - } - }, - "string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", - "dev": true, - "requires": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" - } - }, - "string.prototype.trimend": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", - "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } - } - }, - "string.prototype.trimstart": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", - "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "dev": true, - "requires": { - "define-properties": "^1.1.3", - "es-abstract": "^1.17.5" - }, - "dependencies": { - "es-abstract": { - "version": "1.17.7", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.7.tgz", - "integrity": "sha512-VBl/gnfcJ7OercKA9MVaegWsBHFjV492syMudcnQZvt/Dw8ezpcOHYZXa/J96O8vx+g4x65YKhxOwDUh63aS5g==", - "dev": true, - "requires": { - "es-to-primitive": "^1.2.1", - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-symbols": "^1.0.1", - "is-callable": "^1.2.2", - "is-regex": "^1.1.1", - "object-inspect": "^1.8.0", - "object-keys": "^1.1.1", - "object.assign": "^4.1.1", - "string.prototype.trimend": "^1.0.1", - "string.prototype.trimstart": "^1.0.1" - } - } - } - }, - "string_decoder": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", - "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "~5.1.0" - } - }, - "strip-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", - "dev": true, - "requires": { - "ansi-regex": "^3.0.0" - } - }, - "strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true - }, - "strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", - "dev": true - }, - "stubs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/stubs/-/stubs-3.0.0.tgz", - "integrity": "sha1-6NK6H6nJBXAwPAMLaQD31fiavls=", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - }, - "teeny-request": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/teeny-request/-/teeny-request-7.0.1.tgz", - "integrity": "sha512-sasJmQ37klOlplL4Ia/786M5YlOcoLGQyq2TE4WHSRupbAuDaQW0PfVxV4MtdBtRJ4ngzS+1qim8zP6Zp35qCw==", - "dev": true, - "requires": { - "http-proxy-agent": "^4.0.0", - "https-proxy-agent": "^5.0.0", - "node-fetch": "^2.6.1", - "stream-events": "^1.0.5", - "uuid": "^8.0.0" - } - }, - "terser": { - "version": "4.8.1", - "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", - "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", - "dev": true, - "requires": { - "commander": "^2.20.0", - "source-map": "~0.6.1", - "source-map-support": "~0.5.12" - }, - "dependencies": { - "commander": { - "version": "2.20.3", - "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", - "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } - } - }, - "test-exclude": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz", - "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==", - "dev": true, - "requires": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" - } - }, - "to-fast-properties": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", - "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=", - "dev": true - }, - "to-object-path": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", - "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", - "dev": true, - "optional": true, - "requires": { - "kind-of": "^3.0.2" - }, - "dependencies": { - "kind-of": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", - "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", - "dev": true, - "optional": true, - "requires": { - "is-buffer": "^1.1.5" - } - } - } - }, - "to-regex": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz", - "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==", - "dev": true, - "optional": true, - "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" - } - }, - "to-regex-range": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", - "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", - "dev": true, - "optional": true, - "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" - } - }, - "tr46": { - "version": "0.0.3", - "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", - "dev": true - }, - "ts-node": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.0.0.tgz", - "integrity": "sha512-ROWeOIUvfFbPZkoDis0L/55Fk+6gFQNZwwKPLinacRl6tsxstTF1DbAcLKkovwnpKMVvOMHP1TIbnwXwtLg1gg==", - "dev": true, - "requires": { - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "source-map-support": "^0.5.17", - "yn": "3.1.1" - }, - "dependencies": { - "diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true - } - } - }, - "type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - }, - "typedarray-to-buffer": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz", - "integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==", - "dev": true, - "requires": { - "is-typedarray": "^1.0.0" - } - }, - "typescript": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.3.2.tgz", - "integrity": "sha512-zZ4hShnmnoVnAHpVHWpTcxdv7dWP60S2FsydQLV8V5PbS3FifjWFFRiHSWpDJahly88PRyV5teTSLoq4eG7mKw==", - "dev": true - }, - "unicode-canonical-property-names-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-1.0.4.tgz", - "integrity": "sha512-jDrNnXWHd4oHiTZnx/ZG7gtUTVp+gCcTTKr8L0HjlwphROEW3+Him+IpvC+xcJEFegapiMZyZe02CyuOnRmbnQ==", - "dev": true - }, - "unicode-match-property-ecmascript": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-1.0.4.tgz", - "integrity": "sha512-L4Qoh15vTfntsn4P1zqnHulG0LdXgjSO035fEpdtp6YxXhMT51Q6vgM5lYdG/5X3MjS+k/Y9Xw4SFCY9IkR0rg==", - "dev": true, - "requires": { - "unicode-canonical-property-names-ecmascript": "^1.0.4", - "unicode-property-aliases-ecmascript": "^1.0.4" - } - }, - "unicode-match-property-value-ecmascript": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-1.2.0.tgz", - "integrity": "sha512-wjuQHGQVofmSJv1uVISKLE5zO2rNGzM/KCYZch/QQvez7C1hUhBIuZ701fYXExuufJFMPhv2SyL8CyoIfMLbIQ==", - "dev": true - }, - "unicode-property-aliases-ecmascript": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-1.1.0.tgz", - "integrity": "sha512-PqSoPh/pWetQ2phoj5RLiaqIk4kCNwoV3CI+LfGmWLKI3rE3kl1h59XpX2BjgDrmbxD9ARtQobPGU1SguCYuQg==", - "dev": true - }, - "union-value": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz", - "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==", - "dev": true, - "optional": true, - "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^2.0.1" - } - }, - "unset-value": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", - "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", - "dev": true, - "optional": true, - "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" - }, - "dependencies": { - "has-value": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz", - "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", - "dev": true, - "optional": true, - "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" - }, - "dependencies": { - "isobject": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", - "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk=", - "dev": true, - "optional": true, - "requires": { - "isarray": "1.0.0" - } - } - } - }, - "has-values": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz", - "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E=", - "dev": true, - "optional": true - } - } - }, - "upath": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", - "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", - "dev": true, - "optional": true - }, - "urix": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", - "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", - "dev": true, - "optional": true - }, - "urlgrey": { - "version": "0.4.4", - "resolved": "https://registry.npmjs.org/urlgrey/-/urlgrey-0.4.4.tgz", - "integrity": "sha1-iS/pWWCAXoVRnxzUOJ8stMu3ZS8=", - "dev": true - }, - "use": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz", - "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==", - "dev": true, - "optional": true - }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", - "dev": true, - "optional": true - }, - "uuid": { - "version": "8.3.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.1.tgz", - "integrity": "sha512-FOmRr+FmWEIG8uhZv6C2bTgEVXsHk08kE7mPlrBbEe+c3r9pjceVPgupIfNIhc4yx55H69OXANrUaSuu9eInKg==", - "dev": true - }, - "web-blob": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/web-blob/-/web-blob-2.1.3.tgz", - "integrity": "sha512-7ARypAQxyyqT7ZCHydKavBGCzvvhicGuUMFqg6Xua6H0HIqGgEH1VsMVr1P1Nx+D/maqrUNyOzHkTjBQH/bZOQ==", - "dev": true, - "requires": { - "web-streams-polyfill": "2.1.1" - } - }, - "web-file-polyfill": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/web-file-polyfill/-/web-file-polyfill-1.0.1.tgz", - "integrity": "sha512-Avo1SzN2bpF9w1bmw0Rz455VKjjMgkA32GnDTCvMTNyKs3/7xq3J+yhR1820rqbkIU3LZfx7mU4PTnZXOqQ6uA==", - "dev": true, - "requires": { - "web-blob": "2.1.3" - } - }, - "web-streams-polyfill": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-2.1.1.tgz", - "integrity": "sha512-dlNpL2aab3g8CKfGz6rl8FNmGaRWLLn2g/DtSc9IjB30mEdE6XxzPfPSig5BwGSzI+oLxHyETrQGKjrVVhbLCg==", - "dev": true - }, - "webidl-conversions": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", - "dev": true - }, - "whatwg-url": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", - "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", - "dev": true, - "requires": { - "tr46": "~0.0.3", - "webidl-conversions": "^3.0.0" - } - }, - "which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", - "dev": true, - "requires": { - "isexe": "^2.0.0" - } - }, - "which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "wide-align": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", - "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", - "dev": true, - "requires": { - "string-width": "^1.0.2 || 2" - } - }, - "wrap-ansi": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz", - "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.0", - "string-width": "^3.0.0", - "strip-ansi": "^5.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } - } - } - }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", - "dev": true - }, - "write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dev": true, - "requires": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" - } - }, - "y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==", - "dev": true - }, - "yargs": { - "version": "13.3.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz", - "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==", - "dev": true, - "requires": { - "cliui": "^5.0.0", - "find-up": "^3.0.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^3.0.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^13.1.2" - }, - "dependencies": { - "ansi-regex": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", - "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", - "dev": true - }, - "string-width": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz", - "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==", - "dev": true, - "requires": { - "emoji-regex": "^7.0.1", - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^5.1.0" - } - }, - "strip-ansi": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", - "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", - "dev": true, - "requires": { - "ansi-regex": "^4.1.0" - } + "name": "@imagekit/javascript", + "version": "5.4.1", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "@imagekit/javascript", + "version": "5.4.1", + "license": "Apache-2.0", + "devDependencies": { + "@babel/core": "^7.10.5", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/preset-env": "^7.10.4", + "@babel/preset-typescript": "^7.13.0", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-json": "^4.1.0", + "@rollup/plugin-node-resolve": "^8.4.0", + "@types/node": "^15.6.1", + "rollup": "^2.22.0", + "rollup-plugin-cleanup": "^3.2.1", + "rollup-plugin-terser": "^6.1.0", + "typescript": "^4.3.2" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.8.tgz", + "integrity": "sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.26.10", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.10.tgz", + "integrity": "sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ==", + "dev": true, + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.10", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helpers": "^7.26.10", + "@babel/parser": "^7.26.10", + "@babel/template": "^7.26.9", + "@babel/traverse": "^7.26.10", + "@babel/types": "^7.26.10", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", + "dev": true, + "dependencies": { + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", + "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.26.8", + "@babel/helper-validator-option": "^7.25.9", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz", + "integrity": "sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.27.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.0.tgz", + "integrity": "sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "regexpu-core": "^6.2.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.4.tgz", + "integrity": "sha512-jljfR1rGnXXNWnmQg2K3+bvhkxB51Rl32QRaOTuwwjviGrHzIbSc8+x9CpraDtbT7mfyjXObULP4w/adunNwAw==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", + "dev": true, + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", + "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-wrap-function": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", + "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", + "dev": true, + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", + "dev": true, + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", + "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", + "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", + "dev": true, + "dependencies": { + "@babel/template": "^7.25.9", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", + "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", + "dev": true, + "dependencies": { + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", + "dev": true, + "dependencies": { + "@babel/types": "^7.27.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", + "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", + "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", + "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", + "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", + "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", + "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.26.8.tgz", + "integrity": "sha512-He9Ej2X7tNf2zdKMAGOsmg2MrFc+hfoAhd3po4cWfo/NWjzEAKa0oQruj1ROVUdl0e6fb6/kE/G3SSxE0lRJOg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-remap-async-to-generator": "^7.25.9", + "@babel/traverse": "^7.26.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", + "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-remap-async-to-generator": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.26.5.tgz", + "integrity": "sha512-chuTSY+hq09+/f5lMj8ZSYgCFpppV2CbYrhNFJ1BFoXpiWPnnAb7R0MqrafCpN8E1+YRrtM1MXZHJdIx8B6rMQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.0.tgz", + "integrity": "sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", + "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", + "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", + "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9", + "@babel/traverse": "^7.25.9", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", + "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/template": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", + "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", + "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", + "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", + "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", + "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", + "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.26.9.tgz", + "integrity": "sha512-Hry8AusVm8LW5BVFgiyUReuoGzPUpdHQQqJY5bZnbbf+ngOHWuCuYFKw/BqaaWlvEUrF91HMhDtEaI1hZzNbLg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", + "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", + "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", + "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", + "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", + "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", + "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", + "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", + "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", + "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", + "dev": true, + "dependencies": { + "@babel/helper-module-transforms": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", + "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", + "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.26.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.26.6.tgz", + "integrity": "sha512-CKW8Vu+uUZneQCPtXmSBUC6NCAUdya26hWCElAWh5mVSlSRsmiCPUUDKb3Z0szng1hiAJa098Hkhg9o4SE35Qw==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", + "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", + "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", + "dev": true, + "dependencies": { + "@babel/helper-compilation-targets": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", + "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-replace-supers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", + "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", + "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", + "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", + "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", + "dev": true, + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", + "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", + "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.0.tgz", + "integrity": "sha512-LX/vCajUJQDqE7Aum/ELUMZAY19+cDpghxrnyt5I1tV6X5PyC86AOoWXWFYFeIvauyeSA6/ktn4tQVn/3ZifsA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", + "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", + "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", + "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", + "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", + "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.26.8.tgz", + "integrity": "sha512-OmGDL5/J0CJPJZTHZbi2XpO0tyT2Ia7fzpW5GURwdtp2X3fMmN8au/ej6peC/T33/+CRiIpA8Krse8hFGVmT5Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.0.tgz", + "integrity": "sha512-+LLkxA9rKJpNoGsbLnAgOCdESl73vwYn+V6b+5wHbrE7OGKVDPHIQvbFSzqE6rwqaCw2RE+zdJrlLkcf8YOA0w==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.27.0.tgz", + "integrity": "sha512-fRGGjO2UEGPjvEcyAZXRXAS8AfdaQoq7HnxAbJoAoW10B9xOKesmmndJv+Sym2a+9FHWZ9KbyyLCe9s0Sn5jtg==", + "dev": true, + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.27.0", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", + "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", + "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", + "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", + "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", + "dev": true, + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.9.tgz", + "integrity": "sha512-vX3qPGE8sEKEAZCWk05k3cpTAE3/nOYca++JA+Rd0z2NCNzabmYvEiSShKzm10zdquOIAVXsy2Ei/DTW34KlKQ==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.26.8", + "@babel/helper-compilation-targets": "^7.26.5", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.26.0", + "@babel/plugin-syntax-import-attributes": "^7.26.0", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.25.9", + "@babel/plugin-transform-async-generator-functions": "^7.26.8", + "@babel/plugin-transform-async-to-generator": "^7.25.9", + "@babel/plugin-transform-block-scoped-functions": "^7.26.5", + "@babel/plugin-transform-block-scoping": "^7.25.9", + "@babel/plugin-transform-class-properties": "^7.25.9", + "@babel/plugin-transform-class-static-block": "^7.26.0", + "@babel/plugin-transform-classes": "^7.25.9", + "@babel/plugin-transform-computed-properties": "^7.25.9", + "@babel/plugin-transform-destructuring": "^7.25.9", + "@babel/plugin-transform-dotall-regex": "^7.25.9", + "@babel/plugin-transform-duplicate-keys": "^7.25.9", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-dynamic-import": "^7.25.9", + "@babel/plugin-transform-exponentiation-operator": "^7.26.3", + "@babel/plugin-transform-export-namespace-from": "^7.25.9", + "@babel/plugin-transform-for-of": "^7.26.9", + "@babel/plugin-transform-function-name": "^7.25.9", + "@babel/plugin-transform-json-strings": "^7.25.9", + "@babel/plugin-transform-literals": "^7.25.9", + "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", + "@babel/plugin-transform-member-expression-literals": "^7.25.9", + "@babel/plugin-transform-modules-amd": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.26.3", + "@babel/plugin-transform-modules-systemjs": "^7.25.9", + "@babel/plugin-transform-modules-umd": "^7.25.9", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", + "@babel/plugin-transform-new-target": "^7.25.9", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.26.6", + "@babel/plugin-transform-numeric-separator": "^7.25.9", + "@babel/plugin-transform-object-rest-spread": "^7.25.9", + "@babel/plugin-transform-object-super": "^7.25.9", + "@babel/plugin-transform-optional-catch-binding": "^7.25.9", + "@babel/plugin-transform-optional-chaining": "^7.25.9", + "@babel/plugin-transform-parameters": "^7.25.9", + "@babel/plugin-transform-private-methods": "^7.25.9", + "@babel/plugin-transform-private-property-in-object": "^7.25.9", + "@babel/plugin-transform-property-literals": "^7.25.9", + "@babel/plugin-transform-regenerator": "^7.25.9", + "@babel/plugin-transform-regexp-modifiers": "^7.26.0", + "@babel/plugin-transform-reserved-words": "^7.25.9", + "@babel/plugin-transform-shorthand-properties": "^7.25.9", + "@babel/plugin-transform-spread": "^7.25.9", + "@babel/plugin-transform-sticky-regex": "^7.25.9", + "@babel/plugin-transform-template-literals": "^7.26.8", + "@babel/plugin-transform-typeof-symbol": "^7.26.7", + "@babel/plugin-transform-unicode-escapes": "^7.25.9", + "@babel/plugin-transform-unicode-property-regex": "^7.25.9", + "@babel/plugin-transform-unicode-regex": "^7.25.9", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.11.0", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.40.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.0.tgz", + "integrity": "sha512-vxaPFfJtHhgeOVXRKuHpHPAOgymmy8V8I65T1q53R7GCZlefKeCaTyDs3zOPHTTbmquvNlQYC5klEvWsBAtrBQ==", + "dev": true, + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.26.3", + "@babel/plugin-transform-typescript": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", + "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", + "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", + "dev": true, + "dependencies": { + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dev": true, + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "dev": true, + "dependencies": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-json": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-4.1.0.tgz", + "integrity": "sha512-yfLbTdNS6amI/2OpmbiBoW12vngr5NW2jCJVZSBEz+H5KfUJZ2M7sDjk0U6GOOdCWFVScShte29o9NezJ53TPw==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.0.8" + }, + "peerDependencies": { + "rollup": "^1.20.0 || ^2.0.0" + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-8.4.0.tgz", + "integrity": "sha512-LFqKdRLn0ShtQyf6SBYO69bGE1upV6wUhBX0vFOUnLAyzx5cwp8svA0eHUnu8+YU57XOkrMtfG63QOpQx25pHQ==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "@types/resolve": "1.17.1", + "builtin-modules": "^3.1.0", + "deep-freeze": "^0.0.1", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.17.0" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true + }, + "node_modules/@types/node": { + "version": "15.14.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-15.14.9.tgz", + "integrity": "sha512-qjd88DrCxupx/kJD5yQgZdcYKZKSIGBVDIBE1/LTGcNm3d2Np/jxojkdePDdfnBHJc5W7vSMpbJ1aB7p/Py69A==", + "dev": true + }, + "node_modules/@types/resolve": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.17.1.tgz", + "integrity": "sha512-yy7HuzQhj0dhGpD8RLXSZWEkLsV9ibvxvi6EiJ3bkqLAO1RGo0WbkWQiwpRlSFymTJRz0d3k5LM3kkx8ArDbLw==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.13", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.13.tgz", + "integrity": "sha512-3sX/eOms8kd3q2KZ6DAhKPc0dgm525Gqq5NtWKZ7QYYZEv57OQ54KtblzJzH1lQF/eQxO8KjWGIK9IPUJNus5g==", + "dev": true, + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.4", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.11.1.tgz", + "integrity": "sha512-yGCqvBT4rwMczo28xkH/noxJ6MZ4nJfkVYdoDaC/utLtWrXxv27HVrzAeSbqR8SxDsp46n0YF47EbHoixy6rXQ==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.3", + "core-js-compat": "^3.40.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.4.tgz", + "integrity": "sha512-7gD3pRadPrbjhjLyxebmx/WrFYcuSjZ0XbdUujQMZ/fcE9oeewk2U/7PCvez84UeuK3oSjmPZ0Ch0dlupQvGzw==", + "dev": true, + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.4" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/browserslist": { + "version": "4.24.4", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.4.tgz", + "integrity": "sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001711", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001711.tgz", + "integrity": "sha512-OpFA8GsKtoV3lCcsI3U5XBAV+oVrMu96OS8XafKqnhOaEAW2mveD1Mx81Sx/02chERwhDakuXs28zbyEc4QMKg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/core-js-compat": { + "version": "3.41.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.41.0.tgz", + "integrity": "sha512-RFsU9LySVue9RTwdDVX/T0e2Y6jRYWXERKElIjpuEOEnxaXffI0X7RUwVzfYLfzuLXSNJDYoRYUAmRUcyln20A==", + "dev": true, + "dependencies": { + "browserslist": "^4.24.4" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-freeze": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/deep-freeze/-/deep-freeze-0.0.1.tgz", + "integrity": "sha512-Z+z8HiAvsGwmjqlphnHW5oz6yWlOwu6EQfFTjmeTWlDeda3FS2yv3jhq35TX/ewmsnqB+RX2IdsIOyjJCQN5tg==", + "dev": true + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/electron-to-chromium": { + "version": "1.5.132", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.132.tgz", + "integrity": "sha512-QgX9EBvWGmvSRa74zqfnG7+Eno0Ak0vftBll0Pt2/z5b3bEGYL6OUXLgKPtvx73dn3dvwrlyVkjPKRRlhLYTEg==", + "dev": true + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "dev": true, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dev": true, + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true + }, + "node_modules/jest-worker": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", + "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", + "dev": true, + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/js-cleanup": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/js-cleanup/-/js-cleanup-1.2.0.tgz", + "integrity": "sha512-JeDD0yiiSt80fXzAVa/crrS0JDPQljyBG/RpOtaSbyDq03VHa9szJWMaWOYU/bcTn412uMN2MxApXq8v79cUiQ==", + "dev": true, + "dependencies": { + "magic-string": "^0.25.7", + "perf-regexes": "^1.0.1", + "skip-regex": "^1.0.2" + }, + "engines": { + "node": "^10.14.2 || >=12.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/perf-regexes": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/perf-regexes/-/perf-regexes-1.0.1.tgz", + "integrity": "sha512-L7MXxUDtqr4PUaLFCDCXBfGV/6KLIuSEccizDI7JxT+c9x1G1v04BQ4+4oag84SHaCdrBgQAIs/Cqn+flwFPng==", + "dev": true, + "engines": { + "node": ">=6.14" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true + }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "dev": true, + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regenerator-transform/node_modules/@babel/runtime": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", + "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", + "dev": true, + "dependencies": { + "regenerator-runtime": "^0.14.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/regenerator-transform/node_modules/regenerator-runtime": { + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true + }, + "node_modules/regexpu-core": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", + "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", + "dev": true, + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.0", + "regjsgen": "^0.8.0", + "regjsparser": "^0.12.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true + }, + "node_modules/regjsparser": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", + "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", + "dev": true, + "dependencies": { + "jsesc": "~3.0.2" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", + "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "dev": true, + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/resolve": { + "version": "1.22.10", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", + "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "dev": true, + "dependencies": { + "is-core-module": "^2.16.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/rollup": { + "version": "2.79.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", + "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", + "dev": true, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-cleanup": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-cleanup/-/rollup-plugin-cleanup-3.2.1.tgz", + "integrity": "sha512-zuv8EhoO3TpnrU8MX8W7YxSbO4gmOR0ny06Lm3nkFfq0IVKdBUtHwhVzY1OAJyNCIAdLiyPnOrU0KnO0Fri1GQ==", + "dev": true, + "dependencies": { + "js-cleanup": "^1.2.0", + "rollup-pluginutils": "^2.8.2" + }, + "engines": { + "node": "^10.14.2 || >=12.0.0" + }, + "peerDependencies": { + "rollup": ">=2.0" + } + }, + "node_modules/rollup-plugin-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-terser/-/rollup-plugin-terser-6.1.0.tgz", + "integrity": "sha512-4fB3M9nuoWxrwm39habpd4hvrbrde2W2GG4zEGPQg1YITNkM3Tqur5jSuXlWNzbv/2aMLJ+dZJaySc3GCD8oDw==", + "deprecated": "This package has been deprecated and is no longer maintained. Please use @rollup/plugin-terser", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.8.3", + "jest-worker": "^26.0.0", + "serialize-javascript": "^3.0.0", + "terser": "^4.7.0" + }, + "peerDependencies": { + "rollup": "^2.0.0" + } + }, + "node_modules/rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dev": true, + "dependencies": { + "estree-walker": "^0.6.1" + } + }, + "node_modules/rollup-pluginutils/node_modules/estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==", + "dev": true + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/serialize-javascript": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-3.1.0.tgz", + "integrity": "sha512-JIJT1DGiWmIKhzRsG91aS6Ze4sFUrYbltlkg2onR5OrnNM02Kl/hnY/T4FN2omvyeBbQmMJv+K4cPOpGzOTFBg==", + "dev": true, + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/skip-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/skip-regex/-/skip-regex-1.0.2.tgz", + "integrity": "sha512-pEjMUbwJ5Pl/6Vn6FsamXHXItJXSRftcibixDmNCWbWhic0hzHrwkMZo0IZ7fMRH9KxcWDFSkzhccB4285PutA==", + "dev": true, + "engines": { + "node": ">=4.2" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", + "dev": true + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/terser": { + "version": "4.8.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz", + "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==", + "dev": true, + "dependencies": { + "commander": "^2.20.0", + "source-map": "~0.6.1", + "source-map-support": "~0.5.12" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "dev": true + }, + "node_modules/typescript": { + "version": "4.9.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", + "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", + "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true } - } - }, - "yargs-parser": { - "version": "13.1.2", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz", - "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==", - "dev": true, - "requires": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" - } - }, - "yargs-unparser": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-1.6.0.tgz", - "integrity": "sha512-W9tKgmSn0DpSatfri0nx52Joq5hVXgeLiqR/5G0sZNDoLZFOr/xjBUDcShCOGNsBnEMNo1KAMBkTej1Hm62HTw==", - "dev": true, - "requires": { - "flat": "^4.1.0", - "lodash": "^4.17.15", - "yargs": "^13.3.0" - } - }, - "yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true } - } } diff --git a/package.json b/package.json index cef6c5d..9d81023 100644 --- a/package.json +++ b/package.json @@ -1,51 +1,37 @@ { - "name": "imagekit-javascript", - "version": "1.5.4", - "description": "Javascript SDK for using ImageKit.io in the browser", + "name": "@imagekit/javascript", + "version": "5.4.1", + "description": "ImageKit Javascript SDK", "main": "dist/imagekit.cjs.js", "module": "dist/imagekit.esm.js", "browser": "dist/imagekit.min.js", "unpkg": "dist/imagekit.min.js", - "types": "dist/src/index.d.ts", + "types": "dist/index.d.ts", "files": [ - "dist", - "src" + "dist" ], "devDependencies": { - "@babel/cli": "^7.10.5", "@babel/core": "^7.10.5", + "@babel/plugin-transform-optional-chaining": "^7.25.9", "@babel/preset-env": "^7.10.4", "@babel/preset-typescript": "^7.13.0", - "@babel/register": "^7.14.5", "@rollup/plugin-babel": "^5.2.0", "@rollup/plugin-json": "^4.1.0", "@rollup/plugin-node-resolve": "^8.4.0", - "@rollup/plugin-typescript": "^8.2.1", "@types/node": "^15.6.1", - "babel-plugin-transform-class-properties": "^6.24.1", - "chai": "^4.2.0", - "codecov": "^3.8.0", - "esm": "^3.2.25", - "formdata-node": "2.1.0", - "mocha": "^7.0.1", - "nyc": "^15.1.0", - "regenerator-runtime": "^0.13.9", "rollup": "^2.22.0", "rollup-plugin-cleanup": "^3.2.1", - "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-terser": "^6.1.0", - "sinon": "^8.1.1", - "ts-node": "^10.0.0", - "typescript": "^4.3.2", - "web-file-polyfill": "^1.0.1" + "typescript": "^4.3.2" }, "scripts": { "dev": "rollup -c -w", "export-types": "tsc", "build": "rm -rf dist*;rollup -c && yarn export-types", - "test": "NODE_ENV=test nyc ./node_modules/mocha/bin/mocha test/*.js", - "startSampleApp": "yarn build && cd samples/sample-app/ && yarn install && node index.js", - "report-coverage": "codecov" + "test": "npm run build && cd test-app && npm install && npx playwright install chromium && npx playwright test" + }, + "publishConfig": { + "access": "public" }, "repository": { "type": "git", @@ -54,21 +40,18 @@ "keywords": [ "imagekit", "javascript", - "sdk", - "js", - "sdk", "image", + "video", + "upload", "optimization", - "image", "transformation", - "image", - "resize" + "resize", + "overlay" ], "author": "ImageKit Developer", - "license": "MIT", + "license": "Apache-2.0", "bugs": { "url": "https://github.com/imagekit-developer/imagekit-javascript/issues" }, - "homepage": "https://github.com/imagekit-developer/imagekit-javascript#readme", - "dependencies": {} + "homepage": "https://github.com/imagekit-developer/imagekit-javascript#readme" } diff --git a/release-please-config.json b/release-please-config.json new file mode 100644 index 0000000..e7fbce4 --- /dev/null +++ b/release-please-config.json @@ -0,0 +1,28 @@ +{ + "$schema": "https://raw.githubusercontent.com/googleapis/release-please/main/schemas/config.json", + "packages": { + ".": { + "release-type": "node", + "package-name": "@imagekit/javascript" + } + }, + "include-v-in-tag": true, + "include-component-in-tag": false, + "bump-minor-pre-major": true, + "bump-patch-for-minor-pre-major": false, + "pull-request-header": "Automated Release PR", + "pull-request-title-pattern": "release: ${version}", + "changelog-sections": [ + { "type": "feat", "section": "Features" }, + { "type": "fix", "section": "Bug Fixes" }, + { "type": "perf", "section": "Performance Improvements" }, + { "type": "revert", "section": "Reverts" }, + { "type": "chore", "section": "Chores" }, + { "type": "docs", "section": "Documentation" }, + { "type": "style", "section": "Styles" }, + { "type": "refactor", "section": "Refactors" }, + { "type": "test", "section": "Tests", "hidden": true }, + { "type": "build", "section": "Build System" }, + { "type": "ci", "section": "Continuous Integration", "hidden": true } + ] +} diff --git a/rollup.config.js b/rollup.config.js index 747e961..95ae3de 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -12,8 +12,7 @@ export default [ output: { name: "ImageKit", file: pkg.browser, - format: "umd", - sourceMap: true, + format: "umd" }, plugins: [ nodeResolve({ extensions: [".ts"] }), @@ -34,8 +33,8 @@ export default [ { input: "src/index.ts", output: [ - { file: pkg.main, format: "cjs", exports: "default" }, - { file: pkg.module, format: "es", exports: "default" }, + { file: pkg.main, format: "cjs", exports: "named" }, + { file: pkg.module, format: "es", exports: "named" }, ], plugins: [ nodeResolve({ extensions: [".ts"] }), diff --git a/samples/sample-app/index.js b/samples/sample-app/index.js deleted file mode 100644 index 6f83b2f..0000000 --- a/samples/sample-app/index.js +++ /dev/null @@ -1,36 +0,0 @@ -const path = require('path'); -const open = require('open'); -const dotenv = require('dotenv').config({path: path.join(__dirname, ".env")}); -const server = require('./server/server.js'); - -if (dotenv.error) { - throw new Error(dotenv.error); -} - -const {PRIVATE_KEY, PUBLIC_KEY, URL_ENDPOINT, SERVER_PORT} = dotenv.parsed; - -if (!PRIVATE_KEY || !PUBLIC_KEY || !URL_ENDPOINT || !SERVER_PORT) { - throw new Error("Missing values in the '.env' file.") -} - - -server - .startServer(SERVER_PORT, PUBLIC_KEY, PRIVATE_KEY, URL_ENDPOINT) - .then(() => { - try { - return open(`http://localhost:${SERVER_PORT}`, {wait: true}); - } catch (err){ - console.error(JSON.stringify(err, null, 2)) - } - }) - .then(() => { - console.log("Exiting app."); - process.exit(0); - }) - .catch(err => { - console.log("Error:", JSON.stringify(err, null, 2)); - process.exit(1); - }); - - - diff --git a/samples/sample-app/package.json b/samples/sample-app/package.json deleted file mode 100644 index 3554eae..0000000 --- a/samples/sample-app/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "imagekit-javascript-sample", - "version": "1.0.0", - "description": "Sample app for javascript SDK of ImageKit", - "main": "index.js", - "license": "MIT", - "dependencies": { - "cors": "^2.8.5", - "crypto": "^1.0.1", - "dotenv": "^8.2.0", - "express": "^4.17.1", - "imagekit": "^3.0.3", - "open": "^7.0.2", - "pug": "^3.0.1", - "uuid": "^3.4.0" - } -} diff --git a/samples/sample-app/sample.env b/samples/sample-app/sample.env deleted file mode 100644 index 8276f77..0000000 --- a/samples/sample-app/sample.env +++ /dev/null @@ -1,4 +0,0 @@ -PRIVATE_KEY = your_private_key -PUBLIC_KEY = your_public_key -URL_ENDPOINT = your_url_endpoint -SERVER_PORT = 3000 \ No newline at end of file diff --git a/samples/sample-app/server/server.js b/samples/sample-app/server/server.js deleted file mode 100644 index b0a5982..0000000 --- a/samples/sample-app/server/server.js +++ /dev/null @@ -1,65 +0,0 @@ -const express = require('express'); -const router = express.Router(); -const cors = require('cors'); -const ImageKit = require('imagekit'); -const uuid = require('uuid'); -const fs = require('fs'); -const path = require('path'); - -const pugTemplatePath = path.join(__dirname, "../views/index.pug"); - -const app = express(); -app.use(cors()); -app.set('view engine', 'pug'); - -const startServer = (port = 3000, PUBLIC_KEY, PRIVATE_KEY, URL_ENDPOINT) => { - return new Promise((resolve, reject) => { - try { - const imagekit = new ImageKit({ - publicKey: PUBLIC_KEY, - privateKey: PRIVATE_KEY, - urlEndpoint: URL_ENDPOINT - }); - - - router.get("/auth", (req, res) => { - try { - const token = req.query.token || uuid.v4(); - const expiration = req.query.expire || parseInt(Date.now()/1000)+ (60 * 10); // Default expiration in 10 mins - - const signatureObj = imagekit.getAuthenticationParameters(token, expiration); - - res.status(200).send(signatureObj); - - } catch (err) { - console.error("Error while responding to auth request:", JSON.stringify(err, undefined, 2)); - res.status(500).send("Internal Server Error"); - } - }); - - router.get("/", (req, res) => { - try { - res.render(pugTemplatePath, {publicKey: PUBLIC_KEY, urlEndpoint: URL_ENDPOINT, authenticationEndpoint: `http://localhost:3000/auth`}); - } catch (err) { - console.error("Error while responding to static page request:", JSON.stringify(err, undefined, 2)); - res.status(500).send("Internal Server Error"); - } - }); - - app.use("/",router); - - app.listen(port, () => { - console.info(`Auth server running on port ${port}.`); - resolve(); - }); - } catch (err) { - console.error(JSON.stringify(err, undefined, 2)); - reject("Error starting auth server.") - } - - }); -} - -module.exports = { - startServer -} \ No newline at end of file diff --git a/samples/sample-app/views/index.pug b/samples/sample-app/views/index.pug deleted file mode 100644 index b27d3e9..0000000 --- a/samples/sample-app/views/index.pug +++ /dev/null @@ -1,91 +0,0 @@ -html - body - h3 Imagekit Demo - form(action='#' onSubmit='upload(event)') - input(type='file' id='file1') - input(type="submit") - div(id='info') - div(id='status') - - div(id='images' style='display: none') - - div(id='orig_image') - h4 Original Image - p - img(src="") - div(id='trans_image') - h4 Sample transformation with height: 300, width: 400: - p - img(src="") - - script(type='text/javascript' src="https://unpkg.com/imagekit-javascript/dist/imagekit.min.js") - script. - try { - var imagekit = new ImageKit({ - publicKey: "!{publicKey}", - urlEndpoint: "!{urlEndpoint}", - authenticationEndpoint: "!{authenticationEndpoint}" - }); - - window.imagekit = imagekit; - - - function upload(e) { - e.preventDefault(); - var file = document.getElementById("file1"); - var fileSize = file.files[0].size; - var statusEl = document.getElementById("status"); - statusEl.innerHTML = "Uploading..."; - - // Use this if you want to track upload progress - var customXHR = new XMLHttpRequest(); - customXHR.upload.addEventListener('progress', function (e) { - if (e.loaded <= fileSize) { - var percent = Math.round(e.loaded / fileSize * 100); - console.log(`Uploaded ${percent}%`); - } - - if(e.loaded == e.total){ - console.log("Upload done"); - } - }); - - imagekit.upload({ - xhr: customXHR, // Use this if you want to track upload progress - file : file.files[0], - fileName : file.files[0].name || "test_image.jpg", - tags : ["test_tag_1"], - //- extensions: [ - //- { - //- name: "aws-auto-tagging", - //- minConfidence: 80, - //- maxTags: 10 - //- } - //- ], - }, function(err, result) { - if (err) { - statusEl.innerHTML = "Error uploading image. "+ err.message; - console.log(err) - } else { - statusEl.innerHTML = "File Uploaded"; - var sampleTransformations = [{ HEIGHT: 300, WIDTH: 400}]; - srcUrl = result.url; - transformedURL = imagekit.url({ - src: srcUrl, - transformation : sampleTransformations - }); - - var orig_img = document.querySelector("#orig_image > p > img"); - var trans_img = document.querySelector("#trans_image > p > img"); - - orig_img.setAttribute("src", srcUrl); - trans_img.setAttribute("src", transformedURL); - - var el = document.getElementById('images') - el.setAttribute("style", ""); - } - }); - } - } catch(ex) { - console.log(ex); - } \ No newline at end of file diff --git a/samples/sample-app/yarn.lock b/samples/sample-app/yarn.lock deleted file mode 100644 index cb28aec..0000000 --- a/samples/sample-app/yarn.lock +++ /dev/null @@ -1,997 +0,0 @@ -# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. -# yarn lockfile v1 - - -"@babel/helper-validator-identifier@^7.14.0": - version "7.14.0" - resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288" - integrity sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A== - -"@babel/parser@^7.6.0", "@babel/parser@^7.9.6": - version "7.14.3" - resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.14.3.tgz#9b530eecb071fd0c93519df25c5ff9f14759f298" - integrity sha512-7MpZDIfI7sUC5zWo2+foJ50CSI5lcqDehZ0lVgIhSi4bFEk94fLAKlF3Q0nzSQQ+ca0lm+O6G9ztKVBeu8PMRQ== - -"@babel/types@^7.6.1", "@babel/types@^7.9.6": - version "7.14.2" - resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.14.2.tgz#4208ae003107ef8a057ea8333e56eb64d2f6a2c3" - integrity sha512-SdjAG/3DikRHpUOjxZgnkbR11xUlyDMUFJdvnIgZEE16mqmY0BINMmc4//JMJglEmn6i7sq6p+mGrFWyZ98EEw== - dependencies: - "@babel/helper-validator-identifier" "^7.14.0" - to-fast-properties "^2.0.0" - -accepts@~1.3.7: - version "1.3.7" - resolved "https://registry.yarnpkg.com/accepts/-/accepts-1.3.7.tgz#531bc726517a3b2b41f850021c6cc15eaab507cd" - integrity sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA== - dependencies: - mime-types "~2.1.24" - negotiator "0.6.2" - -acorn@^7.1.1: - version "7.4.1" - resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa" - integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A== - -ajv@^6.12.3: - version "6.12.5" - resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.5.tgz#19b0e8bae8f476e5ba666300387775fb1a00a4da" - integrity sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag== - dependencies: - fast-deep-equal "^3.1.1" - fast-json-stable-stringify "^2.0.0" - json-schema-traverse "^0.4.1" - uri-js "^4.2.2" - -array-flatten@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/array-flatten/-/array-flatten-1.1.1.tgz#9a5f699051b1e7073328f2a008968b64ea2955d2" - integrity sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= - -asap@~2.0.3: - version "2.0.6" - resolved "https://registry.yarnpkg.com/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46" - integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY= - -asn1@~0.2.3: - version "0.2.4" - resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" - integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== - dependencies: - safer-buffer "~2.1.0" - -assert-never@^1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/assert-never/-/assert-never-1.2.1.tgz#11f0e363bf146205fb08193b5c7b90f4d1cf44fe" - integrity sha512-TaTivMB6pYI1kXwrFlEhLeGfOqoDNdTxjCdwRfFFkEA30Eu+k48W34nlok2EYWJfFFzqaEmichdNM7th6M5HNw== - -assert-plus@1.0.0, assert-plus@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" - integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= - -asynckit@^0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" - integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= - -aws-sign2@~0.7.0: - version "0.7.0" - resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" - integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= - -aws4@^1.8.0: - version "1.10.1" - resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.10.1.tgz#e1e82e4f3e999e2cfd61b161280d16a111f86428" - integrity sha512-zg7Hz2k5lI8kb7U32998pRRFin7zJlkfezGJjUc2heaD4Pw2wObakCDVzkKztTm/Ln7eiVvYsjqak0Ed4LkMDA== - -babel-walk@3.0.0-canary-5: - version "3.0.0-canary-5" - resolved "https://registry.yarnpkg.com/babel-walk/-/babel-walk-3.0.0-canary-5.tgz#f66ecd7298357aee44955f235a6ef54219104b11" - integrity sha512-GAwkz0AihzY5bkwIY5QDR+LvsRQgB/B+1foMPvi0FZPMl5fjD7ICiznUiBdLYMH1QYe6vqu4gWYytZOccLouFw== - dependencies: - "@babel/types" "^7.9.6" - -bcrypt-pbkdf@^1.0.0: - version "1.0.2" - resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" - integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= - dependencies: - tweetnacl "^0.14.3" - -body-parser@1.19.0: - version "1.19.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.19.0.tgz#96b2709e57c9c4e09a6fd66a8fd979844f69f08a" - integrity sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw== - dependencies: - bytes "3.1.0" - content-type "~1.0.4" - debug "2.6.9" - depd "~1.1.2" - http-errors "1.7.2" - iconv-lite "0.4.24" - on-finished "~2.3.0" - qs "6.7.0" - raw-body "2.4.0" - type-is "~1.6.17" - -bytes@3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/bytes/-/bytes-3.1.0.tgz#f6cf7933a360e0588fa9fde85651cdc7f805d1f6" - integrity sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg== - -caseless@~0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" - integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= - -character-parser@^2.2.0: - version "2.2.0" - resolved "https://registry.yarnpkg.com/character-parser/-/character-parser-2.2.0.tgz#c7ce28f36d4bcd9744e5ffc2c5fcde1c73261fc0" - integrity sha1-x84o821LzZdE5f/CxfzeHHMmH8A= - dependencies: - is-regex "^1.0.3" - -combined-stream@^1.0.6, combined-stream@~1.0.6: - version "1.0.8" - resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" - integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== - dependencies: - delayed-stream "~1.0.0" - -constantinople@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/constantinople/-/constantinople-4.0.1.tgz#0def113fa0e4dc8de83331a5cf79c8b325213151" - integrity sha512-vCrqcSIq4//Gx74TXXCGnHpulY1dskqLTFGDmhrGxzeXL8lF8kvXv6mpNWlJj1uD4DW23D4ljAqbY4RRaaUZIw== - dependencies: - "@babel/parser" "^7.6.0" - "@babel/types" "^7.6.1" - -content-disposition@0.5.3: - version "0.5.3" - resolved "https://registry.yarnpkg.com/content-disposition/-/content-disposition-0.5.3.tgz#e130caf7e7279087c5616c2007d0485698984fbd" - integrity sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g== - dependencies: - safe-buffer "5.1.2" - -content-type@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" - integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== - -cookie-signature@1.0.6: - version "1.0.6" - resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" - integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= - -cookie@0.4.0: - version "0.4.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.0.tgz#beb437e7022b3b6d49019d088665303ebe9c14ba" - integrity sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg== - -core-util-is@1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" - integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= - -cors@^2.8.5: - version "2.8.5" - resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29" - integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g== - dependencies: - object-assign "^4" - vary "^1" - -crypto@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/crypto/-/crypto-1.0.1.tgz#2af1b7cad8175d24c8a1b0778255794a21803037" - integrity sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig== - -dashdash@^1.12.0: - version "1.14.1" - resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" - integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= - dependencies: - assert-plus "^1.0.0" - -debug@2.6.9: - version "2.6.9" - resolved "https://registry.yarnpkg.com/debug/-/debug-2.6.9.tgz#5d128515df134ff327e90a4c93f4e077a536341f" - integrity sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA== - dependencies: - ms "2.0.0" - -delayed-stream@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" - integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= - -depd@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/depd/-/depd-1.1.2.tgz#9bcd52e14c097763e749b274c4346ed2e560b5a9" - integrity sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= - -destroy@~1.0.4: - version "1.0.4" - resolved "https://registry.yarnpkg.com/destroy/-/destroy-1.0.4.tgz#978857442c44749e4206613e37946205826abd80" - integrity sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= - -doctypes@^1.1.0: - version "1.1.0" - resolved "https://registry.yarnpkg.com/doctypes/-/doctypes-1.1.0.tgz#ea80b106a87538774e8a3a4a5afe293de489e0a9" - integrity sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk= - -dotenv@^8.2.0: - version "8.2.0" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-8.2.0.tgz#97e619259ada750eea3e4ea3e26bceea5424b16a" - integrity sha512-8sJ78ElpbDJBHNeBzUbUVLsqKdccaa/BXF1uPTw3GrvQTBgrQrtObr2mUrE38vzYd8cEv+m/JBfDLioYcfXoaw== - -ecc-jsbn@~0.1.1: - version "0.1.2" - resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" - integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= - dependencies: - jsbn "~0.1.0" - safer-buffer "^2.1.0" - -ee-first@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/ee-first/-/ee-first-1.1.1.tgz#590c61156b0ae2f4f0255732a158b266bc56b21d" - integrity sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= - -encodeurl@~1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" - integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= - -escape-html@~1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" - integrity sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= - -etag@~1.8.1: - version "1.8.1" - resolved "https://registry.yarnpkg.com/etag/-/etag-1.8.1.tgz#41ae2eeb65efa62268aebfea83ac7d79299b0887" - integrity sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= - -express@^4.17.1: - version "4.17.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.17.1.tgz#4491fc38605cf51f8629d39c2b5d026f98a4c134" - integrity sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g== - dependencies: - accepts "~1.3.7" - array-flatten "1.1.1" - body-parser "1.19.0" - content-disposition "0.5.3" - content-type "~1.0.4" - cookie "0.4.0" - cookie-signature "1.0.6" - debug "2.6.9" - depd "~1.1.2" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - finalhandler "~1.1.2" - fresh "0.5.2" - merge-descriptors "1.0.1" - methods "~1.1.2" - on-finished "~2.3.0" - parseurl "~1.3.3" - path-to-regexp "0.1.7" - proxy-addr "~2.0.5" - qs "6.7.0" - range-parser "~1.2.1" - safe-buffer "5.1.2" - send "0.17.1" - serve-static "1.14.1" - setprototypeof "1.1.1" - statuses "~1.5.0" - type-is "~1.6.18" - utils-merge "1.0.1" - vary "~1.1.2" - -extend@~3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" - integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== - -extsprintf@1.3.0: - version "1.3.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" - integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= - -extsprintf@^1.2.0: - version "1.4.0" - resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" - integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= - -fast-deep-equal@^3.1.1: - version "3.1.3" - resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" - integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== - -fast-json-stable-stringify@^2.0.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" - integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== - -finalhandler@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.1.2.tgz#b7e7d000ffd11938d0fdb053506f6ebabe9f587d" - integrity sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA== - dependencies: - debug "2.6.9" - encodeurl "~1.0.2" - escape-html "~1.0.3" - on-finished "~2.3.0" - parseurl "~1.3.3" - statuses "~1.5.0" - unpipe "~1.0.0" - -forever-agent@~0.6.1: - version "0.6.1" - resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" - integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= - -form-data@~2.3.2: - version "2.3.3" - resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" - integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== - dependencies: - asynckit "^0.4.0" - combined-stream "^1.0.6" - mime-types "^2.1.12" - -forwarded@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/forwarded/-/forwarded-0.1.2.tgz#98c23dab1175657b8c0573e8ceccd91b0ff18c84" - integrity sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ= - -fresh@0.5.2: - version "0.5.2" - resolved "https://registry.yarnpkg.com/fresh/-/fresh-0.5.2.tgz#3d8cadd90d976569fa835ab1f8e4b23a105605a7" - integrity sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= - -function-bind@^1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" - integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== - -getpass@^0.1.1: - version "0.1.7" - resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" - integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= - dependencies: - assert-plus "^1.0.0" - -hamming-distance@^1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/hamming-distance/-/hamming-distance-1.0.0.tgz#39bfa46c61f39e87421e4035a1be4f725dd7b931" - integrity sha1-Ob+kbGHznodCHkA1ob5Pcl3XuTE= - -har-schema@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" - integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= - -har-validator@~5.1.3: - version "5.1.5" - resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.5.tgz#1f0803b9f8cb20c0fa13822df1ecddb36bde1efd" - integrity sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w== - dependencies: - ajv "^6.12.3" - har-schema "^2.0.0" - -has-symbols@^1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.1.tgz#9f5214758a44196c406d9bd76cebf81ec2dd31e8" - integrity sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg== - -has@^1.0.3: - version "1.0.3" - resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" - integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== - dependencies: - function-bind "^1.1.1" - -http-errors@1.7.2: - version "1.7.2" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.2.tgz#4f5029cf13239f31036e5b2e55292bcfbcc85c8f" - integrity sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg== - dependencies: - depd "~1.1.2" - inherits "2.0.3" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-errors@~1.7.2: - version "1.7.3" - resolved "https://registry.yarnpkg.com/http-errors/-/http-errors-1.7.3.tgz#6c619e4f9c60308c38519498c14fbb10aacebb06" - integrity sha512-ZTTX0MWrsQ2ZAhA1cejAwDLycFsd7I7nVtnkT3Ol0aqodaKW+0CTZDQ1uBv5whptCnc8e8HeRRJxRs0kmm/Qfw== - dependencies: - depd "~1.1.2" - inherits "2.0.4" - setprototypeof "1.1.1" - statuses ">= 1.5.0 < 2" - toidentifier "1.0.0" - -http-signature@~1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" - integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= - dependencies: - assert-plus "^1.0.0" - jsprim "^1.2.2" - sshpk "^1.7.0" - -iconv-lite@0.4.24: - version "0.4.24" - resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" - integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== - dependencies: - safer-buffer ">= 2.1.2 < 3" - -imagekit@^3.0.3: - version "3.1.0" - resolved "https://registry.yarnpkg.com/imagekit/-/imagekit-3.1.0.tgz#da8c467709feedfbdcb69aadeb0ff8a5e94ad78f" - integrity sha512-DEAywt66fmGwRpgdq9CdW2/eiDBcKodPTnWVmVryJ8JWb7n8z9zAYLDpra/yY7BUgxaGQV2aOm/Cy6ioz9IAFQ== - dependencies: - hamming-distance "^1.0.0" - lodash "^4.17.15" - request "^2.88.0" - uuid "^3.3.3" - -inherits@2.0.3: - version "2.0.3" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" - integrity sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= - -inherits@2.0.4: - version "2.0.4" - resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" - integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== - -ipaddr.js@1.9.1: - version "1.9.1" - resolved "https://registry.yarnpkg.com/ipaddr.js/-/ipaddr.js-1.9.1.tgz#bff38543eeb8984825079ff3a2a8e6cbd46781b3" - integrity sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g== - -is-core-module@^2.2.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.4.0.tgz#8e9fc8e15027b011418026e98f0e6f4d86305cc1" - integrity sha512-6A2fkfq1rfeQZjxrZJGerpLCTHRNEBiSgnu0+obeJpEPZRUooHgsizvzv0ZjJwOz3iWIHdJtVWJ/tmPr3D21/A== - dependencies: - has "^1.0.3" - -is-docker@^2.0.0: - version "2.1.1" - resolved "https://registry.yarnpkg.com/is-docker/-/is-docker-2.1.1.tgz#4125a88e44e450d384e09047ede71adc2d144156" - integrity sha512-ZOoqiXfEwtGknTiuDEy8pN2CfE3TxMHprvNer1mXiqwkOT77Rw3YVrUQ52EqAOU3QAWDQ+bQdx7HJzrv7LS2Hw== - -is-expression@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/is-expression/-/is-expression-4.0.0.tgz#c33155962abf21d0afd2552514d67d2ec16fd2ab" - integrity sha512-zMIXX63sxzG3XrkHkrAPvm/OVZVSCPNkwMHU8oTX7/U3AL78I0QXCEICXUM13BIa8TYGZ68PiTKfQz3yaTNr4A== - dependencies: - acorn "^7.1.1" - object-assign "^4.1.1" - -is-promise@^2.0.0: - version "2.2.2" - resolved "https://registry.yarnpkg.com/is-promise/-/is-promise-2.2.2.tgz#39ab959ccbf9a774cf079f7b40c7a26f763135f1" - integrity sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ== - -is-regex@^1.0.3: - version "1.1.1" - resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.1.tgz#c6f98aacc546f6cec5468a07b7b153ab564a57b9" - integrity sha512-1+QkEcxiLlB7VEyFtyBg94e08OAsvq7FUBgApTq/w2ymCLyKJgDPsybBENVtA7XCQEgEXxKPonG+mvYRxh/LIg== - dependencies: - has-symbols "^1.0.1" - -is-typedarray@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" - integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= - -is-wsl@^2.1.1: - version "2.2.0" - resolved "https://registry.yarnpkg.com/is-wsl/-/is-wsl-2.2.0.tgz#74a4c76e77ca9fd3f932f290c17ea326cd157271" - integrity sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww== - dependencies: - is-docker "^2.0.0" - -isstream@~0.1.2: - version "0.1.2" - resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" - integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= - -js-stringify@^1.0.2: - version "1.0.2" - resolved "https://registry.yarnpkg.com/js-stringify/-/js-stringify-1.0.2.tgz#1736fddfd9724f28a3682adc6230ae7e4e9679db" - integrity sha1-Fzb939lyTyijaCrcYjCufk6Weds= - -jsbn@~0.1.0: - version "0.1.1" - resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" - integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= - -json-schema-traverse@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" - integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== - -json-schema@0.2.3: - version "0.2.3" - resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" - integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= - -json-stringify-safe@~5.0.1: - version "5.0.1" - resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" - integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= - -jsprim@^1.2.2: - version "1.4.1" - resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" - integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= - dependencies: - assert-plus "1.0.0" - extsprintf "1.3.0" - json-schema "0.2.3" - verror "1.10.0" - -jstransformer@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/jstransformer/-/jstransformer-1.0.0.tgz#ed8bf0921e2f3f1ed4d5c1a44f68709ed24722c3" - integrity sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM= - dependencies: - is-promise "^2.0.0" - promise "^7.0.1" - -lodash@^4.17.15: - version "4.17.21" - resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" - integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== - -media-typer@0.3.0: - version "0.3.0" - resolved "https://registry.yarnpkg.com/media-typer/-/media-typer-0.3.0.tgz#8710d7af0aa626f8fffa1ce00168545263255748" - integrity sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= - -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= - -methods@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/methods/-/methods-1.1.2.tgz#5529a4d67654134edcc5266656835b0f851afcee" - integrity sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= - -mime-db@1.44.0: - version "1.44.0" - resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.44.0.tgz#fa11c5eb0aca1334b4233cb4d52f10c5a6272f92" - integrity sha512-/NOTfLrsPBVeH7YtFPgsVWveuL+4SjjYxaQ1xtM1KMFj7HdxlBlxeyNLzhyJVx7r4rZGJAZ/6lkKCitSc/Nmpg== - -mime-types@^2.1.12, mime-types@~2.1.19, mime-types@~2.1.24: - version "2.1.27" - resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.27.tgz#47949f98e279ea53119f5722e0f34e529bec009f" - integrity sha512-JIhqnCasI9yD+SsmkquHBxTSEuZdQX5BuQnS2Vc7puQQQ+8yiP5AY5uWhpdv4YL4VM5c6iliiYWPgJ/nJQLp7w== - dependencies: - mime-db "1.44.0" - -mime@1.6.0: - version "1.6.0" - resolved "https://registry.yarnpkg.com/mime/-/mime-1.6.0.tgz#32cd9e5c64553bd58d19a568af452acff04981b1" - integrity sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg== - -ms@2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8" - integrity sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= - -ms@2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.1.tgz#30a5864eb3ebb0a66f2ebe6d727af06a09d86e0a" - integrity sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg== - -negotiator@0.6.2: - version "0.6.2" - resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.2.tgz#feacf7ccf525a77ae9634436a64883ffeca346fb" - integrity sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw== - -oauth-sign@~0.9.0: - version "0.9.0" - resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" - integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== - -object-assign@^4, object-assign@^4.1.1: - version "4.1.1" - resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" - integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= - -on-finished@~2.3.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/on-finished/-/on-finished-2.3.0.tgz#20f1336481b083cd75337992a16971aa2d906947" - integrity sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= - dependencies: - ee-first "1.1.1" - -open@^7.0.2: - version "7.2.1" - resolved "https://registry.yarnpkg.com/open/-/open-7.2.1.tgz#07b0ade11a43f2a8ce718480bdf3d7563a095195" - integrity sha512-xbYCJib4spUdmcs0g/2mK1nKo/jO2T7INClWd/beL7PFkXRWgr8B23ssDHX/USPn2M2IjDR5UdpYs6I67SnTSA== - dependencies: - is-docker "^2.0.0" - is-wsl "^2.1.1" - -parseurl@~1.3.3: - version "1.3.3" - resolved "https://registry.yarnpkg.com/parseurl/-/parseurl-1.3.3.tgz#9da19e7bee8d12dff0513ed5b76957793bc2e8d4" - integrity sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ== - -path-parse@^1.0.6: - version "1.0.7" - resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" - integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== - -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= - -performance-now@^2.1.0: - version "2.1.0" - resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" - integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= - -promise@^7.0.1: - version "7.3.1" - resolved "https://registry.yarnpkg.com/promise/-/promise-7.3.1.tgz#064b72602b18f90f29192b8b1bc418ffd1ebd3bf" - integrity sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg== - dependencies: - asap "~2.0.3" - -proxy-addr@~2.0.5: - version "2.0.6" - resolved "https://registry.yarnpkg.com/proxy-addr/-/proxy-addr-2.0.6.tgz#fdc2336505447d3f2f2c638ed272caf614bbb2bf" - integrity sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw== - dependencies: - forwarded "~0.1.2" - ipaddr.js "1.9.1" - -psl@^1.1.28: - version "1.8.0" - resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" - integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== - -pug-attrs@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pug-attrs/-/pug-attrs-3.0.0.tgz#b10451e0348165e31fad1cc23ebddd9dc7347c41" - integrity sha512-azINV9dUtzPMFQktvTXciNAfAuVh/L/JCl0vtPCwvOA21uZrC08K/UnmrL+SXGEVc1FwzjW62+xw5S/uaLj6cA== - dependencies: - constantinople "^4.0.1" - js-stringify "^1.0.2" - pug-runtime "^3.0.0" - -pug-code-gen@^3.0.2: - version "3.0.2" - resolved "https://registry.yarnpkg.com/pug-code-gen/-/pug-code-gen-3.0.2.tgz#ad190f4943133bf186b60b80de483100e132e2ce" - integrity sha512-nJMhW16MbiGRiyR4miDTQMRWDgKplnHyeLvioEJYbk1RsPI3FuA3saEP8uwnTb2nTJEKBU90NFVWJBk4OU5qyg== - dependencies: - constantinople "^4.0.1" - doctypes "^1.1.0" - js-stringify "^1.0.2" - pug-attrs "^3.0.0" - pug-error "^2.0.0" - pug-runtime "^3.0.0" - void-elements "^3.1.0" - with "^7.0.0" - -pug-error@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pug-error/-/pug-error-2.0.0.tgz#5c62173cb09c34de2a2ce04f17b8adfec74d8ca5" - integrity sha512-sjiUsi9M4RAGHktC1drQfCr5C5eriu24Lfbt4s+7SykztEOwVZtbFk1RRq0tzLxcMxMYTBR+zMQaG07J/btayQ== - -pug-filters@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pug-filters/-/pug-filters-4.0.0.tgz#d3e49af5ba8472e9b7a66d980e707ce9d2cc9b5e" - integrity sha512-yeNFtq5Yxmfz0f9z2rMXGw/8/4i1cCFecw/Q7+D0V2DdtII5UvqE12VaZ2AY7ri6o5RNXiweGH79OCq+2RQU4A== - dependencies: - constantinople "^4.0.1" - jstransformer "1.0.0" - pug-error "^2.0.0" - pug-walk "^2.0.0" - resolve "^1.15.1" - -pug-lexer@^5.0.0: - version "5.0.1" - resolved "https://registry.yarnpkg.com/pug-lexer/-/pug-lexer-5.0.1.tgz#ae44628c5bef9b190b665683b288ca9024b8b0d5" - integrity sha512-0I6C62+keXlZPZkOJeVam9aBLVP2EnbeDw3An+k0/QlqdwH6rv8284nko14Na7c0TtqtogfWXcRoFE4O4Ff20w== - dependencies: - character-parser "^2.2.0" - is-expression "^4.0.0" - pug-error "^2.0.0" - -pug-linker@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/pug-linker/-/pug-linker-4.0.0.tgz#12cbc0594fc5a3e06b9fc59e6f93c146962a7708" - integrity sha512-gjD1yzp0yxbQqnzBAdlhbgoJL5qIFJw78juN1NpTLt/mfPJ5VgC4BvkoD3G23qKzJtIIXBbcCt6FioLSFLOHdw== - dependencies: - pug-error "^2.0.0" - pug-walk "^2.0.0" - -pug-load@^3.0.0: - version "3.0.0" - resolved "https://registry.yarnpkg.com/pug-load/-/pug-load-3.0.0.tgz#9fd9cda52202b08adb11d25681fb9f34bd41b662" - integrity sha512-OCjTEnhLWZBvS4zni/WUMjH2YSUosnsmjGBB1An7CsKQarYSWQ0GCVyd4eQPMFJqZ8w9xgs01QdiZXKVjk92EQ== - dependencies: - object-assign "^4.1.1" - pug-walk "^2.0.0" - -pug-parser@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/pug-parser/-/pug-parser-6.0.0.tgz#a8fdc035863a95b2c1dc5ebf4ecf80b4e76a1260" - integrity sha512-ukiYM/9cH6Cml+AOl5kETtM9NR3WulyVP2y4HOU45DyMim1IeP/OOiyEWRr6qk5I5klpsBnbuHpwKmTx6WURnw== - dependencies: - pug-error "^2.0.0" - token-stream "1.0.0" - -pug-runtime@^3.0.0: - version "3.0.1" - resolved "https://registry.yarnpkg.com/pug-runtime/-/pug-runtime-3.0.1.tgz#f636976204723f35a8c5f6fad6acda2a191b83d7" - integrity sha512-L50zbvrQ35TkpHwv0G6aLSuueDRwc/97XdY8kL3tOT0FmhgG7UypU3VztfV/LATAvmUfYi4wNxSajhSAeNN+Kg== - -pug-strip-comments@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pug-strip-comments/-/pug-strip-comments-2.0.0.tgz#f94b07fd6b495523330f490a7f554b4ff876303e" - integrity sha512-zo8DsDpH7eTkPHCXFeAk1xZXJbyoTfdPlNR0bK7rpOMuhBYb0f5qUVCO1xlsitYd3w5FQTK7zpNVKb3rZoUrrQ== - dependencies: - pug-error "^2.0.0" - -pug-walk@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/pug-walk/-/pug-walk-2.0.0.tgz#417aabc29232bb4499b5b5069a2b2d2a24d5f5fe" - integrity sha512-yYELe9Q5q9IQhuvqsZNwA5hfPkMJ8u92bQLIMcsMxf/VADjNtEYptU+inlufAFYcWdHlwNfZOEnOOQrZrcyJCQ== - -pug@^3.0.1: - version "3.0.1" - resolved "https://registry.yarnpkg.com/pug/-/pug-3.0.1.tgz#9b287554043e6d18852673a382b0350595bdc067" - integrity sha512-9v1o2yXMfSKJy2PykKyWUhpgx9Pf9D/UlPgIs2pTTxR6DQZ0oivy4I9f8PlWXRY4sjIhDU4TMJ7hQmYnNJc2bw== - dependencies: - pug-code-gen "^3.0.2" - pug-filters "^4.0.0" - pug-lexer "^5.0.0" - pug-linker "^4.0.0" - pug-load "^3.0.0" - pug-parser "^6.0.0" - pug-runtime "^3.0.0" - pug-strip-comments "^2.0.0" - -punycode@^2.1.0, punycode@^2.1.1: - version "2.1.1" - resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" - integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== - -qs@6.7.0: - version "6.7.0" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.7.0.tgz#41dc1a015e3d581f1621776be31afb2876a9b1bc" - integrity sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ== - -qs@~6.5.2: - version "6.5.2" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" - integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== - -range-parser@~1.2.1: - version "1.2.1" - resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" - integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== - -raw-body@2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.4.0.tgz#a1ce6fb9c9bc356ca52e89256ab59059e13d0332" - integrity sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q== - dependencies: - bytes "3.1.0" - http-errors "1.7.2" - iconv-lite "0.4.24" - unpipe "1.0.0" - -request@^2.88.0: - version "2.88.2" - resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" - integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== - dependencies: - aws-sign2 "~0.7.0" - aws4 "^1.8.0" - caseless "~0.12.0" - combined-stream "~1.0.6" - extend "~3.0.2" - forever-agent "~0.6.1" - form-data "~2.3.2" - har-validator "~5.1.3" - http-signature "~1.2.0" - is-typedarray "~1.0.0" - isstream "~0.1.2" - json-stringify-safe "~5.0.1" - mime-types "~2.1.19" - oauth-sign "~0.9.0" - performance-now "^2.1.0" - qs "~6.5.2" - safe-buffer "^5.1.2" - tough-cookie "~2.5.0" - tunnel-agent "^0.6.0" - uuid "^3.3.2" - -resolve@^1.15.1: - version "1.20.0" - resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.20.0.tgz#629a013fb3f70755d6f0b7935cc1c2c5378b1975" - integrity sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A== - dependencies: - is-core-module "^2.2.0" - path-parse "^1.0.6" - -safe-buffer@5.1.2: - version "5.1.2" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" - integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== - -safe-buffer@^5.0.1, safe-buffer@^5.1.2: - version "5.2.1" - resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" - integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== - -"safer-buffer@>= 2.1.2 < 3", safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: - version "2.1.2" - resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" - integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== - -send@0.17.1: - version "0.17.1" - resolved "https://registry.yarnpkg.com/send/-/send-0.17.1.tgz#c1d8b059f7900f7466dd4938bdc44e11ddb376c8" - integrity sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg== - dependencies: - debug "2.6.9" - depd "~1.1.2" - destroy "~1.0.4" - encodeurl "~1.0.2" - escape-html "~1.0.3" - etag "~1.8.1" - fresh "0.5.2" - http-errors "~1.7.2" - mime "1.6.0" - ms "2.1.1" - on-finished "~2.3.0" - range-parser "~1.2.1" - statuses "~1.5.0" - -serve-static@1.14.1: - version "1.14.1" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.14.1.tgz#666e636dc4f010f7ef29970a88a674320898b2f9" - integrity sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg== - dependencies: - encodeurl "~1.0.2" - escape-html "~1.0.3" - parseurl "~1.3.3" - send "0.17.1" - -setprototypeof@1.1.1: - version "1.1.1" - resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.1.tgz#7e95acb24aa92f5885e0abef5ba131330d4ae683" - integrity sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw== - -sshpk@^1.7.0: - version "1.16.1" - resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" - integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== - dependencies: - asn1 "~0.2.3" - assert-plus "^1.0.0" - bcrypt-pbkdf "^1.0.0" - dashdash "^1.12.0" - ecc-jsbn "~0.1.1" - getpass "^0.1.1" - jsbn "~0.1.0" - safer-buffer "^2.0.2" - tweetnacl "~0.14.0" - -"statuses@>= 1.5.0 < 2", statuses@~1.5.0: - version "1.5.0" - resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" - integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= - -to-fast-properties@^2.0.0: - version "2.0.0" - resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" - integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= - -toidentifier@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.0.tgz#7e1be3470f1e77948bc43d94a3c8f4d7752ba553" - integrity sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw== - -token-stream@1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/token-stream/-/token-stream-1.0.0.tgz#cc200eab2613f4166d27ff9afc7ca56d49df6eb4" - integrity sha1-zCAOqyYT9BZtJ/+a/HylbUnfbrQ= - -tough-cookie@~2.5.0: - version "2.5.0" - resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" - integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== - dependencies: - psl "^1.1.28" - punycode "^2.1.1" - -tunnel-agent@^0.6.0: - version "0.6.0" - resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" - integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= - dependencies: - safe-buffer "^5.0.1" - -tweetnacl@^0.14.3, tweetnacl@~0.14.0: - version "0.14.5" - resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" - integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= - -type-is@~1.6.17, type-is@~1.6.18: - version "1.6.18" - resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" - integrity sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g== - dependencies: - media-typer "0.3.0" - mime-types "~2.1.24" - -unpipe@1.0.0, unpipe@~1.0.0: - version "1.0.0" - resolved "https://registry.yarnpkg.com/unpipe/-/unpipe-1.0.0.tgz#b2bf4ee8514aae6165b4817829d21b2ef49904ec" - integrity sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= - -uri-js@^4.2.2: - version "4.4.0" - resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.0.tgz#aa714261de793e8a82347a7bcc9ce74e86f28602" - integrity sha512-B0yRTzYdUCCn9n+F4+Gh4yIDtMQcaJsmYBDsTSG8g/OejKBodLQ2IHfN3bM7jUsRXndopT7OIXWdYqc1fjmV6g== - dependencies: - punycode "^2.1.0" - -utils-merge@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/utils-merge/-/utils-merge-1.0.1.tgz#9f95710f50a267947b2ccc124741c1028427e713" - integrity sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= - -uuid@^3.3.2, uuid@^3.3.3, uuid@^3.4.0: - version "3.4.0" - resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" - integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== - -vary@^1, vary@~1.1.2: - version "1.1.2" - resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc" - integrity sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= - -verror@1.10.0: - version "1.10.0" - resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" - integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= - dependencies: - assert-plus "^1.0.0" - core-util-is "1.0.2" - extsprintf "^1.2.0" - -void-elements@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/void-elements/-/void-elements-3.1.0.tgz#614f7fbf8d801f0bb5f0661f5b2f5785750e4f09" - integrity sha1-YU9/v42AHwu18GYfWy9XhXUOTwk= - -with@^7.0.0: - version "7.0.2" - resolved "https://registry.yarnpkg.com/with/-/with-7.0.2.tgz#ccee3ad542d25538a7a7a80aad212b9828495bac" - integrity sha512-RNGKj82nUPg3g5ygxkQl0R937xLyho1J24ItRCBTr/m1YnZkzJy1hUiHUJrc/VlsDQzsCnInEGSg3bci0Lmd4w== - dependencies: - "@babel/parser" "^7.9.6" - "@babel/types" "^7.9.6" - assert-never "^1.2.1" - babel-walk "3.0.0-canary-5" \ No newline at end of file diff --git a/src/constants/errorMessages.ts b/src/constants/errorMessages.ts index 0787193..4b394f9 100644 --- a/src/constants/errorMessages.ts +++ b/src/constants/errorMessages.ts @@ -1,18 +1,14 @@ export default { - MANDATORY_INITIALIZATION_MISSING: { message: "Missing urlEndpoint during SDK initialization", help: "" }, - INVALID_TRANSFORMATION_POSITION: { message: "Invalid transformationPosition parameter", help: "" }, - PRIVATE_KEY_CLIENT_SIDE: { message: "privateKey should not be passed on the client side", help: "" }, - MISSING_UPLOAD_DATA: { message: "Missing data for upload", help: "" }, - MISSING_UPLOAD_FILE_PARAMETER: { message: "Missing file parameter for upload", help: "" }, - MISSING_UPLOAD_FILENAME_PARAMETER: { message: "Missing fileName parameter for upload", help: "" }, - MISSING_AUTHENTICATION_ENDPOINT: { message: "Missing authentication endpoint for upload", help: "" }, - MISSING_PUBLIC_KEY: { message: "Missing public key for upload", help: "" }, - AUTH_ENDPOINT_TIMEOUT: { message: "The authenticationEndpoint you provided timed out in 60 seconds", help: "" }, - AUTH_ENDPOINT_NETWORK_ERROR: { message: "Request to authenticationEndpoint failed due to network error", help: "" }, - AUTH_INVALID_RESPONSE: { message: "Invalid response from authenticationEndpoint. The SDK expects a JSON response with three fields i.e. signature, token and expire.", help: "" }, + MISSING_UPLOAD_FILE_PARAMETER: { message: "Missing file parameter for upload" }, + MISSING_UPLOAD_FILENAME_PARAMETER: { message: "Missing fileName parameter for upload" }, + MISSING_PUBLIC_KEY: { message: "Missing public key for upload" }, UPLOAD_ENDPOINT_NETWORK_ERROR: { - message: "Request to ImageKit upload endpoint failed due to network error", - help: "", + message: "Request to ImageKit upload endpoint failed due to network error" }, - INVALID_UPLOAD_OPTIONS: { message: "Invalid uploadOptions parameter", help: "" }, + MISSING_SIGNATURE: { message: "Missing signature for upload. The SDK expects token, signature and expire for authentication." }, + MISSING_TOKEN: { message: "Missing token for upload. The SDK expects token, signature and expire for authentication." }, + MISSING_EXPIRE: { message: "Missing expire for upload. The SDK expects token, signature and expire for authentication." }, + INVALID_TRANSFORMATION: { message: "Invalid transformation parameter. Please include at least pre, post, or both." }, + INVALID_PRE_TRANSFORMATION: { message: "Invalid pre transformation parameter." }, + INVALID_POST_TRANSFORMATION: { message: "Invalid post transformation parameter." } }; diff --git a/src/constants/supportedTransforms.ts b/src/constants/supportedTransforms.ts index a459ab2..f5818bf 100644 --- a/src/constants/supportedTransforms.ts +++ b/src/constants/supportedTransforms.ts @@ -1,292 +1,85 @@ /** - * @link https://docs.imagekit.io/features/image-transformations + * {@link https://imagekit.io/docs/transformations} */ -const supportedTransforms: { [key: string]: string } = { - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#width-w - */ +export const supportedTransforms: { [key: string]: string } = { + // Basic sizing & layout width: "w", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#height-h - */ height: "h", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#aspect-ratio-ar - */ aspectRatio: "ar", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#quality-q - */ - quality: "q", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#crop-crop-modes-and-focus - */ + background: "bg", + border: "b", crop: "c", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#crop-crop-modes-and-focus - */ cropMode: "cm", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#focus-fo - */ + dpr: "dpr", focus: "fo", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#examples-focus-using-cropped-image-coordinates - */ + quality: "q", x: "x", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#examples-focus-using-cropped-image-coordinates - */ + xCenter: "xc", y: "y", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#format-f - */ + yCenter: "yc", format: "f", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#radius-r - */ + videoCodec: "vc", + audioCodec: "ac", radius: "r", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#background-color-bg - */ - background: "bg", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#border-b - */ - border: "b", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#rotate-rt - */ rotation: "rt", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#rotate-rt - */ - rotate: "rt", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#blur-bl - */ blur: "bl", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#named-transformation-n - */ named: "n", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-image-oi - */ - overlayImage: "oi", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-image-aspect-ratio-oiar - */ - overlayImageAspectRatio: "oiar", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-image-background-oibg - */ - overlayImageBackground: "oibg", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-image-border-oib - */ - overlayImageBorder: "oib", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-image-dpr-oidpr - */ - overlayImageDPR: "oidpr", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-image-quality-oiq - */ - overlayImageQuality: "oiq", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-image-cropping - */ - overlayImageCropping: "oic", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#trimming-of-the-overlay-image - */ - overlayImageTrim: "oit", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-x-position-ox - */ - overlayX: "ox", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-y-position-oy - */ - overlayY: "oy", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-focus-ofo - */ - overlayFocus: "ofo", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-height-oh - */ - overlayHeight: "oh", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-width-ow - */ - overlayWidth: "ow", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-text-ot - */ - overlayText: "ot", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-text-size-ots - */ - overlayTextFontSize: "ots", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-text-font-otf - */ - overlayTextFontFamily: "otf", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-text-color-otc - */ - overlayTextColor: "otc", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-transparency-oa - */ - overlayTextTransparency: "oa", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-transparency-oa - */ - overlayAlpha: "oa", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-text-typography-ott - */ - overlayTextTypography: "ott", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-background-obg - */ - overlayBackground: "obg", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-text-encoded-ote - */ - overlayTextEncoded: "ote", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-text-width-otw - */ - overlayTextWidth: "otw", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-text-background-otbg - */ - overlayTextBackground: "otbg", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-text-padding-otp - */ - overlayTextPadding: "otp", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-text-inner-alignment-otia - */ - overlayTextInnerAlignment: "otia", - - /** - * @link https://docs.imagekit.io/features/image-transformations/overlay#overlay-radius-or - */ - overlayRadius: "or", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#progressive-image-pr - */ + defaultImage: "di", + flip: "fl", + original: "orig", + startOffset: "so", + endOffset: "eo", + duration: "du", + streamingResolutions: "sr", + + // AI & advanced effects + grayscale: "e-grayscale", + aiUpscale: "e-upscale", + aiRetouch: "e-retouch", + aiVariation: "e-genvar", + aiDropShadow: "e-dropshadow", + aiChangeBackground: "e-changebg", + aiEdit: "e-edit", + aiRemoveBackground: "e-bgremove", + aiRemoveBackgroundExternal: "e-removedotbg", + contrastStretch: "e-contrast", + shadow: "e-shadow", + sharpen: "e-sharpen", + unsharpMask: "e-usm", + gradient: "e-gradient", + colorReplace: "cr", + distort: "e-distort", + colorize: "e-colorize", + + // Other flags & finishing progressive: "pr", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#lossless-webp-and-png-lo - */ lossless: "lo", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#trim-edges-t - */ - trim: "t", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#image-metadata-md - */ - metadata: "md", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#color-profile-cp - */ colorProfile: "cp", + metadata: "md", + opacity: "o", + trim: "t", + zoom: "z", + page: "pg", + layerMode: "lm", + + // Text overlay transformations which are not defined yet + fontSize: "fs", + fontFamily: "ff", + fontColor: "co", + innerAlignment: "ia", + padding: "pa", + alpha: "al", + typography: "tg", + lineHeight: "lh", + + // Subtitles transformations which are not defined + fontOutline: "fol", + fontShadow: "fsh", + + // Raw pass-through + raw: "raw", +}; - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#default-image-di - */ - defaultImage: "di", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#dpr-dpr - */ - dpr: "dpr", - - /** - * @link https://docs.imagekit.io/features/image-transformations/image-enhancement-and-color-manipulation#sharpen-e-sharpen - */ - effectSharpen: "e-sharpen", - - /** - * @link https://docs.imagekit.io/features/image-transformations/image-enhancement-and-color-manipulation#unsharp-mask-e-usm - */ - effectUSM: "e-usm", - - /** - * @link https://docs.imagekit.io/features/image-transformations/image-enhancement-and-color-manipulation#contrast-stretch-e-contrast - */ - effectContrast: "e-contrast", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#grayscale-e-grayscale - */ - effectGray: "e-grayscale", - - /** - * @link https://docs.imagekit.io/features/image-transformations/resize-crop-and-other-transformations#original-image-orig - */ - original: "orig", - - /** - * @link https://docs.imagekit.io/features/image-transformations/conditional-transformations - */ - raw: "raw", -} export default supportedTransforms \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index c6d0bc3..9ccff9e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,103 +1,11 @@ -import { version } from "../package.json"; -import errorMessages from "./constants/errorMessages"; -import { ImageKitOptions, UploadOptions, UploadResponse, UrlOptions } from "./interfaces"; -import IKResponse from "./interfaces/IKResponse"; -import { upload } from "./upload/index"; -import respond from "./utils/respond"; -import { url } from "./url/index"; -import transformationUtils from "./utils/transformation"; - -function mandatoryParametersAvailable(options: ImageKitOptions) { - return options.urlEndpoint; -} - -const promisify = function (thisContext: ImageKit, fn: Function) { - return function (...args: any[]): Promise | void { - if (args.length === fn.length && typeof args[args.length - 1] !== "undefined") { - if (typeof args[args.length - 1] !== "function") { - throw new Error("Callback must be a function."); - } - fn.call(thisContext, ...args); - } else { - return new Promise((resolve, reject) => { - const callback = function (err: Error, ...results: any[]) { - if (err) { - return reject(err); - } else { - resolve(results.length > 1 ? results : results[0]); - } - }; - args.pop() - args.push(callback); - fn.call(thisContext, ...args); - }); - } - }; +import type { GetImageAttributesOptions, ResponsiveImageAttributes, SrcOptions, Transformation, UploadOptions, UploadResponse } from "./interfaces"; +import { getResponsiveImageAttributes } from "./responsive"; +import { ImageKitAbortError, ImageKitInvalidRequestError, ImageKitServerError, ImageKitUploadNetworkError, upload } from "./upload"; +import { buildSrc, buildTransformationString } from "./url"; + +export { buildSrc, buildTransformationString, getResponsiveImageAttributes, ImageKitAbortError, ImageKitInvalidRequestError, ImageKitServerError, ImageKitUploadNetworkError, upload }; +export type { + GetImageAttributesOptions, ResponsiveImageAttributes, SrcOptions, Transformation, UploadOptions, + UploadResponse }; -class ImageKit { - options: ImageKitOptions = { - sdkVersion: `javascript-${version}`, - publicKey: "", - urlEndpoint: "", - transformationPosition: transformationUtils.getDefault(), - }; - - constructor(opts: Omit) { - this.options = { ...this.options, ...(opts || {}) }; - if (!mandatoryParametersAvailable(this.options)) { - throw errorMessages.MANDATORY_INITIALIZATION_MISSING; - } - - if (!transformationUtils.validParameters(this.options)) { - throw errorMessages.INVALID_TRANSFORMATION_POSITION; - } - } - - /** - * You can add multiple origins in the same ImageKit.io account. - * URL endpoints allow you to configure which origins are accessible through your account and set their preference order as well. - * - * @see {@link https://github.com/imagekit-developer/imagekit-nodejs#url-generation} - * @see {@link https://docs.imagekit.io/integration/url-endpoints} - * - * @param urlOptions - */ - url(urlOptions: UrlOptions): string { - return url(urlOptions, this.options); - } - - /** - * You can upload files to ImageKit.io media library from your server-side using private API key authentication. - * - * File size limit - * The maximum upload file size is limited to 25MB. - * - * @see {@link https://docs.imagekit.io/api-reference/upload-file-api/server-side-file-upload} - * - * @param uploadOptions - */ - upload(uploadOptions: UploadOptions, options?: Partial): Promise> - upload(uploadOptions: UploadOptions, callback: (err: Error | null, response: IKResponse | null) => void, options?: Partial): void; - upload(uploadOptions: UploadOptions, callbackOrOptions?: ((err: Error | null, response: IKResponse | null) => void) | Partial, options?: Partial): void | Promise> { - let callback; - if (typeof callbackOrOptions === 'function') { - callback = callbackOrOptions; - } else { - options = callbackOrOptions || {}; - } - if (!uploadOptions || typeof uploadOptions !== "object") { - return respond(true, errorMessages.INVALID_UPLOAD_OPTIONS, callback); - } - var mergedOptions = { - ...this.options, - ...options, - }; - const { xhr: userProvidedXHR } = uploadOptions || {}; - delete uploadOptions.xhr; - const xhr = userProvidedXHR || new XMLHttpRequest(); - return promisify>(this, upload)(xhr, uploadOptions, mergedOptions, callback); - } -} - -export default ImageKit; diff --git a/src/interfaces/IKResponse.ts b/src/interfaces/IKResponse.ts deleted file mode 100644 index a53ca4f..0000000 --- a/src/interfaces/IKResponse.ts +++ /dev/null @@ -1,10 +0,0 @@ -interface ResponseMetadata { - statusCode: number; - headers: Record; -} - -type IKResponse = T extends Error - ? T & { $ResponseMetadata?: ResponseMetadata } - : T & { $ResponseMetadata: ResponseMetadata }; - -export default IKResponse; diff --git a/src/interfaces/ImageKitOptions.ts b/src/interfaces/ImageKitOptions.ts deleted file mode 100644 index 2ba4bcd..0000000 --- a/src/interfaces/ImageKitOptions.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { TransformationPosition } from "."; - -export interface ImageKitOptions { - urlEndpoint: string; - sdkVersion?: string; - publicKey?: string; - authenticationEndpoint?: string; - transformationPosition?: TransformationPosition; -} \ No newline at end of file diff --git a/src/interfaces/Transformation.ts b/src/interfaces/Transformation.ts deleted file mode 100644 index 0c74022..0000000 --- a/src/interfaces/Transformation.ts +++ /dev/null @@ -1,5 +0,0 @@ -import supportedTransforms from "../constants/supportedTransforms"; - -export type TransformationPosition = "path" | "query"; - -export type Transformation = Partial; diff --git a/src/interfaces/UploadOptions.ts b/src/interfaces/UploadOptions.ts index 24f18ec..e57fdc8 100644 --- a/src/interfaces/UploadOptions.ts +++ b/src/interfaces/UploadOptions.ts @@ -1,106 +1,322 @@ +import * as Shared from './shared'; + /** - * Options used when uploading a file - * - * @link https://docs.imagekit.io/api-reference/upload-file-api/server-side-file-upload#request-structure-multipart-form-data + * Options used when uploading a file using the V1 API. + * Check out the official documentation: + * {@link https://imagekit.io/docs/api-reference/upload-file/upload-file} */ export interface UploadOptions { /** - * This field accepts three kinds of values: - * - binary - You can send the content of the file as binary. This is used when a file is being uploaded from the browser. - * - base64 - Base64 encoded string of file content. - * - url - URL of the file from where to download the content before uploading. - * Downloading file from URL might take longer, so it is recommended that you pass the binary or base64 content of the file. - * Pass the full URL, for example - https://www.example.com/rest-of-the-image-path.jpg. + * The API accepts any of the following: + * + * - **Binary data** – send the raw bytes as `multipart/form-data`. + * - **HTTP / HTTPS URL** – a publicly reachable URL that ImageKit’s servers can + * fetch. + * - **Base64 string** – the file encoded as a Base64 data URI or plain Base64. + * + * When supplying a URL, the server must receive the response headers within 8 + * seconds; otherwise the request fails with 400 Bad Request. */ file: string | Blob | File; + /** - * The name with which the file has to be uploaded. - * The file name can contain: - * - Alphanumeric Characters: a-z , A-Z , 0-9 (including unicode letters, marks, and numerals in other languages) - * - Special Characters: . _ and - - * Any other character including space will be replaced by _ + * The name with which the file has to be uploaded. The file name can contain: + * + * - Alphanumeric Characters: `a-z`, `A-Z`, `0-9`. + * - Special Characters: `.`, `-` + * + * Any other character including space will be replaced by `_` */ fileName: string; + /** - * Whether to use a unique filename for this file or not. - * - Accepts true or false. - * - If set true, ImageKit.io will add a unique suffix to the filename parameter to get a unique filename. - * - If set false, then the image is uploaded with the provided filename parameter and any existing file with the same name is replaced. - * Default value - true + * A unique value that the ImageKit.io server will use to recognize and prevent + * subsequent retries for the same request. We suggest using V4 UUIDs, or another + * random string with enough entropy to avoid collisions. + * + * **Note**: Sending a value that has been used in the past will result in a + * validation error. Even if your previous request resulted in an error, you should + * always send a new value for this field. */ - useUniqueFileName?: boolean; + token: string; + + /** + * Server-side checks to run on the asset. Read more about + * [Upload API checks](/docs/api-reference/upload-file/upload-file#upload-api-checks). + */ + checks?: string; + + /** + * Define an important area in the image. This is only relevant for image type + * files. + * + * - To be passed as a string with the x and y coordinates of the top-left corner, + * and width and height of the area of interest in the format `x,y,width,height`. + * For example - `10,10,100,100` + * - Can be used with fo-customtransformation. + * - If this field is not specified and the file is overwritten, then + * customCoordinates will be removed. + */ + customCoordinates?: string; + + /** + * JSON key-value pairs to associate with the asset. Create the custom metadata + * fields before setting these values. + */ + customMetadata?: { [key: string]: unknown }; + /** - * Set the tags while uploading the file. - * - Comma-separated value of tags in format tag1,tag2,tag3. For example - t-shirt,round-neck,men - * - The maximum length of all characters should not exceed 500. - * - % is not allowed. - * - If this field is not specified and the file is overwritten then the tags will be removed. + * Optional text to describe the contents of the file. */ - tags?: string | string[]; + description?: string; + /** - * The folder path (e.g. /images/folder/) in which the image has to be uploaded. If the folder(s) didn't exist before, a new folder(s) is created. + * The time until your signature is valid. It must be a + * [Unix time](https://en.wikipedia.org/wiki/Unix_time) in less than 1 hour into + * the future. It should be in seconds. + */ + expire: number; + + /** + * Array of extensions to be applied to the asset. Each extension can be configured + * with specific parameters based on the extension type. + */ + extensions?: Shared.Extensions; + + /** + * The folder path in which the image has to be uploaded. If the folder(s) didn't + * exist before, a new folder(s) is created. + * * The folder name can contain: - * - Alphanumeric Characters: a-z , A-Z , 0-9 (including unicode letters, marks, and numerals in other languages) - * - Special Characters: / _ and - - * - Using multiple / creates a nested folder. - * Default value - / + * + * - Alphanumeric Characters: `a-z` , `A-Z` , `0-9` + * - Special Characters: `/` , `_` , `-` + * + * Using multiple `/` creates a nested folder. */ folder?: string; + /** - * Whether to mark the file as private or not. This is only relevant for image type files. - * - Accepts true or false. - * - If set true, the file is marked as private which restricts access to the original image URL and unnamed image transformations without signed URLs. - * Without the signed URL, only named transformations work on private images - * Default value - false + * Whether to mark the file as private or not. + * + * If `true`, the file is marked as private and is accessible only using named + * transformation or signed URL. */ isPrivateFile?: boolean; + /** - * Define an important area in the image. This is only relevant for image type files. - * To be passed as a string with the x and y coordinates of the top-left corner, and width and height of the area of interest in format x,y,width,height. For example - 10,10,100,100 - * Can be used with fo-customtransformation. - * If this field is not specified and the file is overwritten, then customCoordinates will be removed. + * Whether to upload file as published or not. + * + * If `false`, the file is marked as unpublished, which restricts access to the + * file only via the media library. Files in draft or unpublished state can only be + * publicly accessed after being published. + * + * The option to upload in draft state is only available in custom enterprise + * pricing plans. */ - customCoordinates?: string; + isPublished?: boolean; + /** - * Comma-separated values of the fields that you want ImageKit.io to return in response. - * - * For example, set the value of this field to tags,customCoordinates,isPrivateFile,metadata to get value of tags, customCoordinates, isPrivateFile , and metadata in the response. + * If set to `true` and a file already exists at the exact location, its AITags + * will be removed. Set `overwriteAITags` to `false` to preserve AITags. */ - responseFields?: string | string[]; - /* - * Object with array of extensions to be processed on the image. + overwriteAITags?: boolean; + + /** + * If the request does not have `customMetadata`, and a file already exists at the + * exact location, existing customMetadata will be removed. */ - extensions?: object[]; - /* - * Final status of pending extensions will be sent to this URL. + overwriteCustomMetadata?: boolean; + + /** + * If `false` and `useUniqueFileName` is also `false`, and a file already exists at + * the exact location, upload API will return an error immediately. */ - webhookUrl?: string - /* - * Default is true. If overwriteFile is set to false and useUniqueFileName is also false, and a file already exists at the exact location, upload API will return an error immediately. + overwriteFile?: boolean; + + /** + * If the request does not have `tags`, and a file already exists at the exact + * location, existing tags will be removed. */ - overwriteFile?: boolean - /* - * Default is true. If set to true and a file already exists at the exact location, its AITags will be removed. Set overwriteAITags to false to preserve AITags. + overwriteTags?: boolean; + + /** + * The public API key of your ImageKit account. + * You can find it in the [ImageKit dashboard](https://imagekit.io/dashboard/developer/api-keys). + */ + publicKey: string; + + /** + * Array of response field keys to include in the API response body. + */ + responseFields?: Array< + | 'tags' + | 'customCoordinates' + | 'isPrivateFile' + | 'embeddedMetadata' + | 'isPublished' + | 'customMetadata' + | 'metadata' + | 'selectedFieldsSchema' + >; + + /** + * The HMAC-SHA1 digest of the concatenation of "token + expire". The signing key is your ImageKit private API key. + * Calculate this signature in your secure server and pass it to the client. + */ + signature: string; + + /** + * Set the tags while uploading the file. Provide an array of tag strings (e.g. + * `["tag1", "tag2", "tag3"]`). The combined length of all tag characters must not + * exceed 500, and the `%` character is not allowed. If this field is not specified + * and the file is overwritten, the existing tags will be removed. */ - overwriteAITags?: boolean - /* - * Default is true. If the request does not have tags , overwriteTags is set to true and a file already exists at the exact location, existing tags will be removed. - * In case the request body has tags, setting overwriteTags to false has no effect and request's tags are set on the asset. + tags?: Array; + + /** + * Configure pre-processing (`pre`) and post-processing (`post`) transformations. + * + * - `pre` — applied before the file is uploaded to the Media Library. + * Useful for reducing file size or applying basic optimizations upfront (e.g., + * resize, compress). + * + * - `post` — applied immediately after upload. + * Ideal for generating transformed versions (like video encodes or thumbnails) + * in advance, so they're ready for delivery without delay. + * + * You can mix and match any combination of post-processing types. + */ + transformation?: FileUploadParams.Transformation; + + /** + * Whether to use a unique filename for this file or not. + * + * If `true`, ImageKit.io will add a unique suffix to the filename parameter to get + * a unique filename. + * + * If `false`, then the image is uploaded with the provided filename parameter, and + * any existing file with the same name is replaced. + */ + useUniqueFileName?: boolean; + + /** + * The final status of extensions after they have completed execution will be + * delivered to this endpoint as a POST request. + * [Learn more](/docs/api-reference/digital-asset-management-dam/managing-assets/update-file-details#webhook-payload-structure) + * about the webhook payload structure. */ - overwriteTags?: boolean - /* - * Default is true. If the request does not have customMetadata , overwriteCustomMetadata is set to true and a file already exists at the exact location, exiting customMetadata will be removed. - * In case the request body has customMetadata, setting overwriteCustomMetadata to false has no effect and request's customMetadata is set on the asset. + webhookUrl?: string; + + // JS SDK specific options + + /** + * An optional XMLHttpRequest instance for the upload. The SDK merges it with its own logic to handle progress events, etc. + * You can listen to `progress` or other events on this object for custom logic. */ - overwriteCustomMetadata?: boolean - /* - * Stringified JSON key-value data to be associated with the asset. Checkout overwriteCustomMetadata parameter to understand default behaviour. - * Before setting any custom metadata on an asset you have to create the field using custom metadata fields API. + xhr?: XMLHttpRequest; + + /** + * Optional callback function that will be called with the progress event when the file is being uploaded. */ - customMetadata?: string | Record> + onProgress?: (event: ProgressEvent) => void; /** - * Optional XMLHttpRequest object that you can send for upload API request. You can listen to `progress` and other events on this object for any custom logic. + * An AbortSignal instance that can be used to cancel the request if needed. + * When aborted, the request fails with an ImageKitAbortError. */ - xhr?: XMLHttpRequest + abortSignal?: AbortSignal; } + +export namespace FileUploadParams { + /** + * Configure pre-processing (`pre`) and post-processing (`post`) transformations. + * + * - `pre` — applied before the file is uploaded to the Media Library. + * Useful for reducing file size or applying basic optimizations upfront (e.g., + * resize, compress). + * + * - `post` — applied immediately after upload. + * Ideal for generating transformed versions (like video encodes or thumbnails) + * in advance, so they're ready for delivery without delay. + * + * You can mix and match any combination of post-processing types. + */ + export interface Transformation { + /** + * List of transformations to apply _after_ the file is uploaded. + * Each item must match one of the following types: `transformation`, + * `gif-to-video`, `thumbnail`, `abs`. + */ + post?: Array< + | Transformation.Transformation + | Transformation.GifToVideo + | Transformation.Thumbnail + | Transformation.Abs + >; + + /** + * Transformation string to apply before uploading the file to the Media Library. + * Useful for optimizing files at ingestion. + */ + pre?: string; + } + + export namespace Transformation { + export interface Transformation { + /** + * Transformation type. + */ + type: 'transformation'; + + /** + * Transformation string (e.g. `w-200,h-200`). + * Same syntax as ImageKit URL-based transformations. + */ + value: string; + } + + export interface GifToVideo { + /** + * Converts an animated GIF into an MP4. + */ + type: 'gif-to-video'; + + /** + * Optional transformation string to apply to the output video. + * **Example**: `q-80` + */ + value?: string; + } + + export interface Thumbnail { + /** + * Generates a thumbnail image. + */ + type: 'thumbnail'; + + /** + * Optional transformation string. + * **Example**: `w-150,h-150` + */ + value?: string; + } + + export interface Abs { + /** + * Streaming protocol to use (`hls` or `dash`). + */ + protocol: 'hls' | 'dash'; + + /** + * Adaptive Bitrate Streaming (ABS) setup. + */ + type: 'abs'; + + /** + * List of different representations you want to create separated by an underscore. + */ + value: string; + } + } +} \ No newline at end of file diff --git a/src/interfaces/UploadResponse.ts b/src/interfaces/UploadResponse.ts index e3e2f93..2c9f4e8 100644 --- a/src/interfaces/UploadResponse.ts +++ b/src/interfaces/UploadResponse.ts @@ -1,162 +1,521 @@ /** - * Type of files to include in result set. Accepts three values: - * all - include all types of files in result set - * image - only search in image type files - * non-image - only search in files which are not image, e.g., JS or CSS or video files. - * - * @link https://docs.imagekit.io/api-reference/media-api/list-and-search-files - */ -export type FileType = "all" | "image" | "non-image"; - -/** - * Metadata object structure - * @link https://docs.imagekit.io/api-reference/metadata-api#metadata-object-structure - * - * Contents of Object - * - * - Exif - * - * For more information about the Exif standard, please refer to the specification found on http://www.exif.org. A comprehensive list of available Exif attributes and their meaning can be found on http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/. - * - * - Perceptual Hash (pHash) - * - * Perceptual hashing allows you to construct a hash value that uniquely identifies an input image based on the image's contents. It is different from cryptographic hash functions like MD5 and SHA1. pHash provides similar hash value after minor distortions, like small rotations, blurring, and compression in the image. + * JSON object containing metadata. */ export interface Metadata { - height: number; - width: number; - size: number; - format: string; - hasColorProfile: boolean; - quality: number; - density: number; - hasTransparency: boolean; - pHash: string; - exif: { - image: { - Make: string; - Model: string; - Orientation: number; - XResolution: number; - YResolution: number; - ResolutionUnit: number; - Software: string; - ModifyDate: string; - YCbCrPositioning: number; - ExifOffset: number; - GPSInfo: number; - }; - thumbnail: { - Compression: number; - XResolution: number; - YResolution: number; - ResolutionUnit: number; - ThumbnailOffset: number; - ThumbnailLength: number; - }; - exif: { - ExposureTime: number; - FNumber: number; - ExposureProgram: number; - ISO: number; - ExifVersion: string; - DateTimeOriginal: string; - CreateDate: string; - ShutterSpeedValue: number; - ApertureValue: number; - ExposureCompensation: number; - MeteringMode: number; - Flash: number; - FocalLength: number; - SubSecTime: string; - SubSecTimeOriginal: string; - SubSecTimeDigitized: string; - FlashpixVersion: string; - ColorSpace: number; - ExifImageWidth: number; - ExifImageHeight: number; - InteropOffset: number; - FocalPlaneXResolution: number; - FocalPlaneYResolution: number; - FocalPlaneResolutionUnit: number; - CustomRendered: number; - ExposureMode: number; - WhiteBalance: number; - SceneCaptureType: number; - }; - gps: { GPSVersionID: number[] }; - interoperability: { - InteropIndex: string; - InteropVersion: string; - }; - makernote: any; - }; + /** + * The audio codec used in the video (only for video). + */ + audioCodec?: string; + + /** + * The bit rate of the video in kbps (only for video). + */ + bitRate?: number; + + /** + * The density of the image in DPI. + */ + density?: number; + + /** + * The duration of the video in seconds (only for video). + */ + duration?: number; + + exif?: Metadata.Exif; + + /** + * The format of the file (e.g., 'jpg', 'mp4'). + */ + format?: string; + + /** + * Indicates if the image has a color profile. + */ + hasColorProfile?: boolean; + + /** + * Indicates if the image contains transparent areas. + */ + hasTransparency?: boolean; + + /** + * The height of the image or video in pixels. + */ + height?: number; + + /** + * Perceptual hash of the image. + */ + pHash?: string; + + /** + * The quality indicator of the image. + */ + quality?: number; + + /** + * The file size in bytes. + */ + size?: number; + + /** + * The video codec used in the video (only for video). + */ + videoCodec?: string; + + /** + * The width of the image or video in pixels. + */ + width?: number; +} + +export namespace Metadata { + export interface Exif { + /** + * Object containing Exif details. + */ + exif?: Exif.Exif; + + /** + * Object containing GPS information. + */ + gps?: Exif.Gps; + + /** + * Object containing EXIF image information. + */ + image?: Exif.Image; + + /** + * JSON object. + */ + interoperability?: Exif.Interoperability; + + makernote?: { [key: string]: unknown }; + + /** + * Object containing Thumbnail information. + */ + thumbnail?: Exif.Thumbnail; + } + + export namespace Exif { + /** + * Object containing Exif details. + */ + export interface Exif { + ApertureValue?: number; + + ColorSpace?: number; + + CreateDate?: string; + + CustomRendered?: number; + + DateTimeOriginal?: string; + + ExifImageHeight?: number; + + ExifImageWidth?: number; + + ExifVersion?: string; + + ExposureCompensation?: number; + + ExposureMode?: number; + + ExposureProgram?: number; + + ExposureTime?: number; + + Flash?: number; + + FlashpixVersion?: string; + + FNumber?: number; + + FocalLength?: number; + + FocalPlaneResolutionUnit?: number; + + FocalPlaneXResolution?: number; + + FocalPlaneYResolution?: number; + + InteropOffset?: number; + + ISO?: number; + + MeteringMode?: number; + + SceneCaptureType?: number; + + ShutterSpeedValue?: number; + + SubSecTime?: string; + + WhiteBalance?: number; + } + + /** + * Object containing GPS information. + */ + export interface Gps { + GPSVersionID?: Array; + } + + /** + * Object containing EXIF image information. + */ + export interface Image { + ExifOffset?: number; + + GPSInfo?: number; + + Make?: string; + + Model?: string; + + ModifyDate?: string; + + Orientation?: number; + + ResolutionUnit?: number; + + Software?: string; + + XResolution?: number; + + YCbCrPositioning?: number; + + YResolution?: number; + } + + /** + * JSON object. + */ + export interface Interoperability { + InteropIndex?: string; + + InteropVersion?: string; + } + + /** + * Object containing Thumbnail information. + */ + export interface Thumbnail { + Compression?: number; + + ResolutionUnit?: number; + + ThumbnailLength?: number; + + ThumbnailOffset?: number; + + XResolution?: number; + + YResolution?: number; + } + } +} + +export interface ResponseMetadata { + statusCode: number; + requestId: string; + headers: Record; } /** - * Response from uploading a file - * - * @link https://docs.imagekit.io/api-reference/upload-file-api/server-side-file-upload#response-code-and-structure-json + * Object containing details of a successful upload. */ export interface UploadResponse { /** - * Unique fileId. Store this fileld in your database, as this will be used to perform update action on this file. + * An array of tags assigned to the uploaded file by auto tagging. + */ + AITags?: Array | null; + + /** + * The audio codec used in the video (only for video). */ - fileId: string; + audioCodec?: string; + /** - * The name of the uploaded file. + * The bit rate of the video in kbps (only for video). */ - name: string; + bitRate?: number; + /** - * The URL of the file. + * Value of custom coordinates associated with the image in the format + * `x,y,width,height`. If `customCoordinates` are not defined, then it is `null`. + * Send `customCoordinates` in `responseFields` in API request to get the value of + * this field. */ - url: string; + customCoordinates?: string | null; + /** - * In case of an image, a small thumbnail URL. + * A key-value data associated with the asset. Use `responseField` in API request + * to get `customMetadata` in the upload API response. Before setting any custom + * metadata on an asset, you have to create the field using custom metadata fields + * API. Send `customMetadata` in `responseFields` in API request to get the value + * of this field. */ - thumbnailUrl: string; + customMetadata?: { [key: string]: unknown }; + + /** + * Optional text to describe the contents of the file. Can be set by the user or + * the ai-auto-description extension. + */ + description?: string; + + /** + * The duration of the video in seconds (only for video). + */ + duration?: number; + /** - * Height of the uploaded image file. Only applicable when file type is image. + * Consolidated embedded metadata associated with the file. It includes exif, iptc, + * and xmp data. Send `embeddedMetadata` in `responseFields` in API request to get + * embeddedMetadata in the upload API response. */ - height: number; + embeddedMetadata?: { [key: string]: unknown }; + /** - * Width of the uploaded image file. Only applicable when file type is image. + * Extension names with their processing status at the time of completion of the + * request. It could have one of the following status values: + * + * `success`: The extension has been successfully applied. `failed`: The extension + * has failed and will not be retried. `pending`: The extension will finish + * processing in some time. On completion, the final status (success / failed) will + * be sent to the `webhookUrl` provided. + * + * If no extension was requested, then this parameter is not returned. */ - width: number; + extensionStatus?: FileUploadResponse.ExtensionStatus; + /** - * Size of the uploaded file in bytes. + * Unique fileId. Store this fileld in your database, as this will be used to + * perform update action on this file. */ - size: number; + fileId?: string; + /** - * Type of file. It can either be image or non-image. + * The relative path of the file in the media library e.g. + * `/marketing-assets/new-banner.jpg`. */ - fileType: FileType; + filePath?: string; + /** - * The path of the file uploaded. It includes any folder that you specified while uploading. + * Type of the uploaded file. Possible values are `image`, `non-image`. */ - filePath: string; + fileType?: string; + /** - * Array of tags associated with the image. + * Height of the image in pixels (Only for images) */ - tags?: string[]; + height?: number; + /** - * Is the file marked as private. It can be either true or false. + * Is the file marked as private. It can be either `true` or `false`. Send + * `isPrivateFile` in `responseFields` in API request to get the value of this + * field. */ - isPrivateFile: boolean; + isPrivateFile?: boolean; + /** - * Value of custom coordinates associated with the image in format x,y,width,height. + * Is the file published or in draft state. It can be either `true` or `false`. + * Send `isPublished` in `responseFields` in API request to get the value of this + * field. */ - customCoordinates: string | null; + isPublished?: boolean; + /** - * The metadata of the upload file. Use responseFields property in request to get the metadata returned in response of upload API. + * Legacy metadata. Send `metadata` in `responseFields` in API request to get + * metadata in the upload API response. */ metadata?: Metadata; - /* - * AITags field is populated only because the google-auto-tagging extension was executed synchronously and it received a successresponse. - */ - AITags?: object[]; - /* - * Field object which will contain the status of each extension at the time of completion of the update/upload request. - */ - extensionStatus?: { [key: string]: string } + + /** + * Name of the asset. + */ + name?: string; + + /** + * This field is included in the response only if the Path policy feature is + * available in the plan. It contains schema definitions for the custom metadata + * fields selected for the specified file path. Field selection can only be done + * when the Path policy feature is enabled. + * + * Keys are the names of the custom metadata fields; the value object has details + * about the custom metadata schema. + */ + selectedFieldsSchema?: { [key: string]: FileUploadResponse.SelectedFieldsSchema }; + + /** + * Size of the image file in Bytes. + */ + size?: number; + + /** + * The array of tags associated with the asset. If no tags are set, it will be + * `null`. Send `tags` in `responseFields` in API request to get the value of this + * field. + */ + tags?: Array | null; + + /** + * In the case of an image, a small thumbnail URL. + */ + thumbnailUrl?: string; + + /** + * A publicly accessible URL of the file. + */ + url?: string; + + /** + * An object containing the file or file version's `id` (versionId) and `name`. + */ + versionInfo?: FileUploadResponse.VersionInfo; + + /** + * The video codec used in the video (only for video). + */ + videoCodec?: string; + + /** + * Width of the image in pixels (Only for Images) + */ + width?: number; + + /** + * Message indicating that the file upload is accepted. This field is only present when the upload is accepted but not yet processed. + * This can happen when the file is being processed for pre-transformation for video. + * The upload will be completed once the pre-transformation is done. + */ + message?: string + + /** + * Response metadata for debugging purposes. + */ + readonly $ResponseMetadata: ResponseMetadata; } + +export namespace FileUploadResponse { + export interface AITag { + /** + * Confidence score of the tag. + */ + confidence?: number; + + /** + * Name of the tag. + */ + name?: string; + + /** + * Array of `AITags` associated with the image. If no `AITags` are set, it will be + * null. These tags can be added using the `google-auto-tagging` or + * `aws-auto-tagging` extensions. + */ + source?: string; + } + + /** + * Extension names with their processing status at the time of completion of the + * request. It could have one of the following status values: + * + * `success`: The extension has been successfully applied. `failed`: The extension + * has failed and will not be retried. `pending`: The extension will finish + * processing in some time. On completion, the final status (success / failed) will + * be sent to the `webhookUrl` provided. + * + * If no extension was requested, then this parameter is not returned. + */ + export interface ExtensionStatus { + 'ai-auto-description'?: 'success' | 'pending' | 'failed'; + + 'ai-tasks'?: 'success' | 'pending' | 'failed'; + + 'aws-auto-tagging'?: 'success' | 'pending' | 'failed'; + + 'google-auto-tagging'?: 'success' | 'pending' | 'failed'; + + 'remove-bg'?: 'success' | 'pending' | 'failed'; + } + + export interface SelectedFieldsSchema { + /** + * Type of the custom metadata field. + */ + type: 'Text' | 'Textarea' | 'Number' | 'Date' | 'Boolean' | 'SingleSelect' | 'MultiSelect'; + + /** + * The default value for this custom metadata field. The value should match the + * `type` of custom metadata field. + */ + defaultValue?: string | number | boolean | Array; + + /** + * Specifies if the custom metadata field is required or not. + */ + isValueRequired?: boolean; + + /** + * Maximum length of string. Only set if `type` is set to `Text` or `Textarea`. + */ + maxLength?: number; + + /** + * Maximum value of the field. Only set if field type is `Date` or `Number`. For + * `Date` type field, the value will be in ISO8601 string format. For `Number` type + * field, it will be a numeric value. + */ + maxValue?: string | number; + + /** + * Minimum length of string. Only set if `type` is set to `Text` or `Textarea`. + */ + minLength?: number; + + /** + * Minimum value of the field. Only set if field type is `Date` or `Number`. For + * `Date` type field, the value will be in ISO8601 string format. For `Number` type + * field, it will be a numeric value. + */ + minValue?: string | number; + + /** + * Indicates whether the custom metadata field is read only. A read only field + * cannot be modified after being set. This field is configurable only via the + * **Path policy** feature. + */ + readOnly?: boolean; + + /** + * An array of allowed values when field type is `SingleSelect` or `MultiSelect`. + */ + selectOptions?: Array; + + /** + * Specifies if the selectOptions array is truncated. It is truncated when number + * of options are > 100. + */ + selectOptionsTruncated?: boolean; + } + + /** + * An object containing the file or file version's `id` (versionId) and `name`. + */ + export interface VersionInfo { + /** + * Unique identifier of the file version. + */ + id?: string; + + /** + * Name of the file version. + */ + name?: string; + } +} \ No newline at end of file diff --git a/src/interfaces/UrlOptions.ts b/src/interfaces/UrlOptions.ts deleted file mode 100644 index c6af45d..0000000 --- a/src/interfaces/UrlOptions.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { TransformationPosition } from "."; -import { Transformation } from "./Transformation"; - -export interface UrlOptionsBase { - /** - * An array of objects specifying the transformations to be applied in the URL. - * The transformation name and the value should be specified as a key-value pair in each object. - * @link https://docs.imagekit.io/features/image-transformations/chained-transformations - */ - transformation?: Array; - /** - * Default value is path that places the transformation string as a path parameter in the URL. - * Can also be specified as query which adds the transformation string as the query parameter tr in the URL. - * If you use src parameter to create the URL, then the transformation string is always added as a query parameter. - */ - transformationPosition?: TransformationPosition; - /** - * These are the other query parameters that you want to add to the final URL. - * These can be any query parameters and not necessarily related to ImageKit. - * Especially useful, if you want to add some versioning parameter to your URLs. - */ - queryParameters?: { [key: string]: string | number }; - /** - * The base URL to be appended before the path of the image. - * If not specified, the URL Endpoint specified at the time of SDK initialization is used. - */ - urlEndpoint?: string; -} - -export interface UrlOptionsSrc extends UrlOptionsBase { - /** - * Conditional. This is the complete URL of an image already mapped to ImageKit. - * For example, https://ik.imagekit.io/your_imagekit_id/endpoint/path/to/image.jpg. - * Either the path or src parameter need to be specified for URL generation. - */ - src: string; - path?: never; -} - -export interface UrlOptionsPath extends UrlOptionsBase { - /** - * Conditional. This is the path at which the image exists. - * For example, /path/to/image.jpg. Either the path or src parameter need to be specified for URL generation. - */ - path: string; - src?: never; -} - -/** - * Options for generating an URL - * - * @link https://github.com/imagekit-developer/imagekit-javascript#url-generation - */ -export type UrlOptions = UrlOptionsSrc | UrlOptionsPath; diff --git a/src/interfaces/index.ts b/src/interfaces/index.ts index 50afe5c..639daaf 100644 --- a/src/interfaces/index.ts +++ b/src/interfaces/index.ts @@ -1,7 +1,6 @@ -import { ImageKitOptions } from "./ImageKitOptions"; -import { TransformationPosition } from "./Transformation"; -import { UploadOptions } from "./UploadOptions"; -import { UploadResponse, FileType } from "./UploadResponse"; -import { UrlOptions } from "./UrlOptions"; +// src/interfaces/index.ts +// Re-export all interfaces so that TypeDoc includes referenced types in the documentation -export type { ImageKitOptions, TransformationPosition, UploadOptions, UploadResponse, FileType, UrlOptions }; +export * from './shared'; +export * from './UploadResponse'; +export * from './UploadOptions'; \ No newline at end of file diff --git a/src/interfaces/shared.ts b/src/interfaces/shared.ts new file mode 100644 index 0000000..d7561cc --- /dev/null +++ b/src/interfaces/shared.ts @@ -0,0 +1,1781 @@ +// File generated from our OpenAPI spec by Stainless with some overrides. + +export interface BaseOverlay { + /** + * Controls how the layer blends with the base image or underlying content. Maps to + * `lm` in the URL. By default, layers completely cover the base image beneath + * them. Layer modes change this behavior: + * + * - `multiply`: Multiplies the pixel values of the layer with the base image. The + * result is always darker than the original images. This is ideal for applying + * shadows or color tints. + * - `displace`: Uses the layer as a displacement map to distort pixels in the base + * image. The red channel controls horizontal displacement, and the green channel + * controls vertical displacement. Requires `x` or `y` parameter to control + * displacement magnitude. + * - `cutout`: Acts as an inverse mask where opaque areas of the layer turn the + * base image transparent, while transparent areas leave the base image + * unchanged. This mode functions like a hole-punch, effectively cutting the + * shape of the layer out of the underlying image. + * - `cutter`: Acts as a shape mask where only the parts of the base image that + * fall inside the opaque area of the layer are preserved. This mode functions + * like a cookie-cutter, trimming the base image to match the specific dimensions + * and shape of the layer. See + * [Layer modes](https://imagekit.io/docs/add-overlays-on-images#layer-modes). + */ + layerMode?: 'multiply' | 'cutter' | 'cutout' | 'displace'; + + /** + * Specifies the overlay's position relative to the parent asset. See + * [Position of Layer](https://imagekit.io/docs/transformations#position-of-layer). + */ + position?: OverlayPosition; + + /** + * Specifies timing information for the overlay (only applicable if the base asset + * is a video). See + * [Position of Layer](https://imagekit.io/docs/transformations#position-of-layer). + */ + timing?: OverlayTiming; +} + +/** + * Configuration object for an extension (base extensions only, not saved extension + * references). + */ +export type ExtensionConfig = + | ExtensionConfig.RemoveBg + | ExtensionConfig.AutoTaggingExtension + | ExtensionConfig.AIAutoDescription + | ExtensionConfig.AITasks; + +export namespace ExtensionConfig { + export interface RemoveBg { + /** + * Specifies the background removal extension. + */ + name: 'remove-bg'; + + options?: RemoveBg.Options; + } + + export namespace RemoveBg { + export interface Options { + /** + * Whether to add an artificial shadow to the result. Default is false. Note: + * Adding shadows is currently only supported for car photos. + */ + add_shadow?: boolean; + + /** + * Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or + * color name (e.g., "green"). If this parameter is set, `bg_image_url` must be + * empty. + */ + bg_color?: string; + + /** + * Sets a background image from a URL. If this parameter is set, `bg_color` must be + * empty. + */ + bg_image_url?: string; + + /** + * Allows semi-transparent regions in the result. Default is true. Note: + * Semitransparency is currently only supported for car windows. + */ + semitransparency?: boolean; + } + } + + export interface AutoTaggingExtension { + /** + * Maximum number of tags to attach to the asset. + */ + maxTags: number; + + /** + * Minimum confidence level for tags to be considered valid. + */ + minConfidence: number; + + /** + * Specifies the auto-tagging extension used. + */ + name: 'google-auto-tagging' | 'aws-auto-tagging'; + } + + export interface AIAutoDescription { + /** + * Specifies the auto description extension. + */ + name: 'ai-auto-description'; + } + + export interface AITasks { + /** + * Specifies the AI tasks extension for automated image analysis using AI models. + */ + name: 'ai-tasks'; + + /** + * Array of task objects defining AI operations to perform on the asset. + */ + tasks: Array; + } + + export namespace AITasks { + export interface SelectTags { + /** + * The question or instruction for the AI to analyze the image. + */ + instruction: string; + + /** + * Task type that analyzes the image and adds matching tags from a vocabulary. + */ + type: 'select_tags'; + + /** + * Maximum number of tags to select from the vocabulary. + */ + max_selections?: number; + + /** + * Minimum number of tags to select from the vocabulary. + */ + min_selections?: number; + + /** + * Array of possible tag values. The combined length of all strings must not exceed + * 500 characters, and values cannot include the `%` character. When providing + * large vocabularies (more than 30 items), the AI may not follow the list + * strictly. + */ + vocabulary?: Array; + } + + export interface SelectMetadata { + /** + * Name of the custom metadata field to set. The field must exist in your account. + */ + field: string; + + /** + * The question or instruction for the AI to analyze the image. + */ + instruction: string; + + /** + * Task type that analyzes the image and sets a custom metadata field value from a + * vocabulary. + */ + type: 'select_metadata'; + + /** + * Maximum number of values to select from the vocabulary. + */ + max_selections?: number; + + /** + * Minimum number of values to select from the vocabulary. + */ + min_selections?: number; + + /** + * An array of possible values matching the custom metadata field type. If not + * provided for SingleSelect or MultiSelect field types, all values from the custom + * metadata field definition will be used. When providing large vocabularies (above + * 30 items), the AI may not strictly adhere to the list. + */ + vocabulary?: Array; + } + + export interface YesNo { + /** + * The yes/no question for the AI to answer about the image. + */ + instruction: string; + + /** + * Task type that asks a yes/no question and executes actions based on the answer. + */ + type: 'yes_no'; + + /** + * Actions to execute if the AI answers no. + */ + on_no?: YesNo.OnNo; + + /** + * Actions to execute if the AI cannot determine the answer. + */ + on_unknown?: YesNo.OnUnknown; + + /** + * Actions to execute if the AI answers yes. + */ + on_yes?: YesNo.OnYes; + } + + export namespace YesNo { + /** + * Actions to execute if the AI answers no. + */ + export interface OnNo { + /** + * Array of tag strings to add to the asset. + */ + add_tags?: Array; + + /** + * Array of tag strings to remove from the asset. + */ + remove_tags?: Array; + + /** + * Array of custom metadata field updates. + */ + set_metadata?: Array; + + /** + * Array of custom metadata fields to remove. + */ + unset_metadata?: Array; + } + + export namespace OnNo { + export interface SetMetadata { + /** + * Name of the custom metadata field to set. + */ + field: string; + + /** + * Value to set for the custom metadata field. The value type should match the + * custom metadata field type. + */ + value: string | number | boolean | Array; + } + + export interface UnsetMetadata { + /** + * Name of the custom metadata field to remove. + */ + field: string; + } + } + + /** + * Actions to execute if the AI cannot determine the answer. + */ + export interface OnUnknown { + /** + * Array of tag strings to add to the asset. + */ + add_tags?: Array; + + /** + * Array of tag strings to remove from the asset. + */ + remove_tags?: Array; + + /** + * Array of custom metadata field updates. + */ + set_metadata?: Array; + + /** + * Array of custom metadata fields to remove. + */ + unset_metadata?: Array; + } + + export namespace OnUnknown { + export interface SetMetadata { + /** + * Name of the custom metadata field to set. + */ + field: string; + + /** + * Value to set for the custom metadata field. The value type should match the + * custom metadata field type. + */ + value: string | number | boolean | Array; + } + + export interface UnsetMetadata { + /** + * Name of the custom metadata field to remove. + */ + field: string; + } + } + + /** + * Actions to execute if the AI answers yes. + */ + export interface OnYes { + /** + * Array of tag strings to add to the asset. + */ + add_tags?: Array; + + /** + * Array of tag strings to remove from the asset. + */ + remove_tags?: Array; + + /** + * Array of custom metadata field updates. + */ + set_metadata?: Array; + + /** + * Array of custom metadata fields to remove. + */ + unset_metadata?: Array; + } + + export namespace OnYes { + export interface SetMetadata { + /** + * Name of the custom metadata field to set. + */ + field: string; + + /** + * Value to set for the custom metadata field. The value type should match the + * custom metadata field type. + */ + value: string | number | boolean | Array; + } + + export interface UnsetMetadata { + /** + * Name of the custom metadata field to remove. + */ + field: string; + } + } + } + } +} + +/** + * Array of extensions to be applied to the asset. Each extension can be configured + * with specific parameters based on the extension type. + */ +export type Extensions = Array< + | Extensions.RemoveBg + | Extensions.AutoTaggingExtension + | Extensions.AIAutoDescription + | Extensions.AITasks + | Extensions.SavedExtension +>; + +export namespace Extensions { + export interface RemoveBg { + /** + * Specifies the background removal extension. + */ + name: 'remove-bg'; + + options?: RemoveBg.Options; + } + + export namespace RemoveBg { + export interface Options { + /** + * Whether to add an artificial shadow to the result. Default is false. Note: + * Adding shadows is currently only supported for car photos. + */ + add_shadow?: boolean; + + /** + * Specifies a solid color background using hex code (e.g., "81d4fa", "fff") or + * color name (e.g., "green"). If this parameter is set, `bg_image_url` must be + * empty. + */ + bg_color?: string; + + /** + * Sets a background image from a URL. If this parameter is set, `bg_color` must be + * empty. + */ + bg_image_url?: string; + + /** + * Allows semi-transparent regions in the result. Default is true. Note: + * Semitransparency is currently only supported for car windows. + */ + semitransparency?: boolean; + } + } + + export interface AutoTaggingExtension { + /** + * Maximum number of tags to attach to the asset. + */ + maxTags: number; + + /** + * Minimum confidence level for tags to be considered valid. + */ + minConfidence: number; + + /** + * Specifies the auto-tagging extension used. + */ + name: 'google-auto-tagging' | 'aws-auto-tagging'; + } + + export interface AIAutoDescription { + /** + * Specifies the auto description extension. + */ + name: 'ai-auto-description'; + } + + export interface AITasks { + /** + * Specifies the AI tasks extension for automated image analysis using AI models. + */ + name: 'ai-tasks'; + + /** + * Array of task objects defining AI operations to perform on the asset. + */ + tasks: Array; + } + + export namespace AITasks { + export interface SelectTags { + /** + * The question or instruction for the AI to analyze the image. + */ + instruction: string; + + /** + * Task type that analyzes the image and adds matching tags from a vocabulary. + */ + type: 'select_tags'; + + /** + * Maximum number of tags to select from the vocabulary. + */ + max_selections?: number; + + /** + * Minimum number of tags to select from the vocabulary. + */ + min_selections?: number; + + /** + * Array of possible tag values. The combined length of all strings must not exceed + * 500 characters, and values cannot include the `%` character. When providing + * large vocabularies (more than 30 items), the AI may not follow the list + * strictly. + */ + vocabulary?: Array; + } + + export interface SelectMetadata { + /** + * Name of the custom metadata field to set. The field must exist in your account. + */ + field: string; + + /** + * The question or instruction for the AI to analyze the image. + */ + instruction: string; + + /** + * Task type that analyzes the image and sets a custom metadata field value from a + * vocabulary. + */ + type: 'select_metadata'; + + /** + * Maximum number of values to select from the vocabulary. + */ + max_selections?: number; + + /** + * Minimum number of values to select from the vocabulary. + */ + min_selections?: number; + + /** + * An array of possible values matching the custom metadata field type. If not + * provided for SingleSelect or MultiSelect field types, all values from the custom + * metadata field definition will be used. When providing large vocabularies (above + * 30 items), the AI may not strictly adhere to the list. + */ + vocabulary?: Array; + } + + export interface YesNo { + /** + * The yes/no question for the AI to answer about the image. + */ + instruction: string; + + /** + * Task type that asks a yes/no question and executes actions based on the answer. + */ + type: 'yes_no'; + + /** + * Actions to execute if the AI answers no. + */ + on_no?: YesNo.OnNo; + + /** + * Actions to execute if the AI cannot determine the answer. + */ + on_unknown?: YesNo.OnUnknown; + + /** + * Actions to execute if the AI answers yes. + */ + on_yes?: YesNo.OnYes; + } + + export namespace YesNo { + /** + * Actions to execute if the AI answers no. + */ + export interface OnNo { + /** + * Array of tag strings to add to the asset. + */ + add_tags?: Array; + + /** + * Array of tag strings to remove from the asset. + */ + remove_tags?: Array; + + /** + * Array of custom metadata field updates. + */ + set_metadata?: Array; + + /** + * Array of custom metadata fields to remove. + */ + unset_metadata?: Array; + } + + export namespace OnNo { + export interface SetMetadata { + /** + * Name of the custom metadata field to set. + */ + field: string; + + /** + * Value to set for the custom metadata field. The value type should match the + * custom metadata field type. + */ + value: string | number | boolean | Array; + } + + export interface UnsetMetadata { + /** + * Name of the custom metadata field to remove. + */ + field: string; + } + } + + /** + * Actions to execute if the AI cannot determine the answer. + */ + export interface OnUnknown { + /** + * Array of tag strings to add to the asset. + */ + add_tags?: Array; + + /** + * Array of tag strings to remove from the asset. + */ + remove_tags?: Array; + + /** + * Array of custom metadata field updates. + */ + set_metadata?: Array; + + /** + * Array of custom metadata fields to remove. + */ + unset_metadata?: Array; + } + + export namespace OnUnknown { + export interface SetMetadata { + /** + * Name of the custom metadata field to set. + */ + field: string; + + /** + * Value to set for the custom metadata field. The value type should match the + * custom metadata field type. + */ + value: string | number | boolean | Array; + } + + export interface UnsetMetadata { + /** + * Name of the custom metadata field to remove. + */ + field: string; + } + } + + /** + * Actions to execute if the AI answers yes. + */ + export interface OnYes { + /** + * Array of tag strings to add to the asset. + */ + add_tags?: Array; + + /** + * Array of tag strings to remove from the asset. + */ + remove_tags?: Array; + + /** + * Array of custom metadata field updates. + */ + set_metadata?: Array; + + /** + * Array of custom metadata fields to remove. + */ + unset_metadata?: Array; + } + + export namespace OnYes { + export interface SetMetadata { + /** + * Name of the custom metadata field to set. + */ + field: string; + + /** + * Value to set for the custom metadata field. The value type should match the + * custom metadata field type. + */ + value: string | number | boolean | Array; + } + + export interface UnsetMetadata { + /** + * Name of the custom metadata field to remove. + */ + field: string; + } + } + } + } + + export interface SavedExtension { + /** + * The unique ID of the saved extension to apply. + */ + id: string; + + /** + * Indicates this is a reference to a saved extension. + */ + name: 'saved-extension'; + } +} + +/** + * Options for generating responsive image attributes including `src`, `srcSet`, + * and `sizes` for HTML `` elements. This schema extends `SrcOptions` to add + * support for responsive image generation with breakpoints. + */ +export interface GetImageAttributesOptions extends SrcOptions { + /** + * Custom list of **device-width breakpoints** in pixels. These define common + * screen widths for responsive image generation. + * + * Defaults to `[640, 750, 828, 1080, 1200, 1920, 2048, 3840]`. Sorted + * automatically. + */ + deviceBreakpoints?: Array; + + /** + * Custom list of **image-specific breakpoints** in pixels. Useful for generating + * small variants (e.g., placeholders or thumbnails). + * + * Merged with `deviceBreakpoints` before calculating `srcSet`. Defaults to + * `[16, 32, 48, 64, 96, 128, 256, 384]`. Sorted automatically. + */ + imageBreakpoints?: Array; + + /** + * The value for the HTML `sizes` attribute (e.g., `"100vw"` or + * `"(min-width:768px) 50vw, 100vw"`). + * + * - If it includes one or more `vw` units, breakpoints smaller than the + * corresponding percentage of the smallest device width are excluded. + * - If it contains no `vw` units, the full breakpoint list is used. + * + * Enables a width-based strategy and generates `w` descriptors in `srcSet`. + */ + sizes?: string; + + /** + * The intended display width of the image in pixels, used **only when the `sizes` + * attribute is not provided**. + * + * Triggers a DPR-based strategy (1x and 2x variants) and generates `x` descriptors + * in `srcSet`. + * + * Ignored if `sizes` is present. + */ + width?: number; +} + +export interface ImageOverlay extends BaseOverlay { + /** + * Specifies the relative path to the image used as an overlay. + */ + input: string; + + type: 'image'; + + /** + * The input path can be included in the layer as either `i-{input}` or + * `ie-{base64_encoded_input}`. By default, the SDK determines the appropriate + * format automatically. To always use base64 encoding (`ie-{base64}`), set this + * parameter to `base64`. To always use plain text (`i-{input}`), set it to + * `plain`. + * + * Regardless of the encoding method: + * + * - Leading and trailing slashes are removed. + * - Remaining slashes within the path are replaced with `@@` when using plain + * text. + */ + encoding?: 'auto' | 'plain' | 'base64'; + + /** + * Array of transformations to be applied to the overlay image. Supported + * transformations depends on the base/parent asset. See overlays on + * [Images](https://imagekit.io/docs/add-overlays-on-images#list-of-supported-image-transformations-in-image-layers) + * and + * [Videos](https://imagekit.io/docs/add-overlays-on-videos#list-of-transformations-supported-on-image-overlay). + */ + transformation?: Array; +} + +/** + * Specifies an overlay to be applied on the parent image or video. ImageKit + * supports overlays including images, text, videos, subtitles, and solid colors. + * See + * [Overlay using layers](https://imagekit.io/docs/transformations#overlay-using-layers). + */ +export type Overlay = TextOverlay | ImageOverlay | VideoOverlay | SubtitleOverlay | SolidColorOverlay; + +export interface OverlayPosition { + /** + * Sets the anchor point on the base asset from which the overlay offset is + * calculated. The default value is `top_left`. Maps to `lap` in the URL. Can only + * be used with one or more of `x`, `y`, `xCenter`, or `yCenter`. + */ + anchorPoint?: + | 'top' + | 'left' + | 'right' + | 'bottom' + | 'top_left' + | 'top_right' + | 'bottom_left' + | 'bottom_right' + | 'center'; + + /** + * Specifies the position of the overlay relative to the parent image or video. If + * one or more of `x`, `y`, `xCenter`, or `yCenter` parameters are specified, this + * parameter is ignored. Maps to `lfo` in the URL. + */ + focus?: + | 'center' + | 'top' + | 'left' + | 'bottom' + | 'right' + | 'top_left' + | 'top_right' + | 'bottom_left' + | 'bottom_right'; + + /** + * Specifies the x-coordinate of the top-left corner of the base asset where the + * overlay's top-left corner will be positioned. It also accepts arithmetic + * expressions such as `bw_mul_0.4` or `bw_sub_cw`. Maps to `lx` in the URL. Learn + * about + * [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + */ + x?: number | string; + + /** + * Specifies the x-coordinate on the base asset where the overlay's center will be + * positioned. It also accepts arithmetic expressions such as `bw_mul_0.4` or + * `bw_sub_cw`. Maps to `lxc` in the URL. Cannot be used together with `x`, but can + * be used with `y`. Learn about + * [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + */ + xCenter?: number | string; + + /** + * Specifies the y-coordinate of the top-left corner of the base asset where the + * overlay's top-left corner will be positioned. It also accepts arithmetic + * expressions such as `bh_mul_0.4` or `bh_sub_ch`. Maps to `ly` in the URL. Learn + * about + * [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + */ + y?: number | string; + + /** + * Specifies the y-coordinate on the base asset where the overlay's center will be + * positioned. It also accepts arithmetic expressions such as `bh_mul_0.4` or + * `bh_sub_ch`. Maps to `lyc` in the URL. Cannot be used together with `y`, but can + * be used with `x`. Learn about + * [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + */ + yCenter?: number | string; +} + +export interface OverlayTiming { + /** + * Specifies the duration (in seconds) during which the overlay should appear on + * the base video. Accepts a positive number up to two decimal places (e.g., `20` + * or `20.50`) and arithmetic expressions such as `bdu_mul_0.4` or `bdu_sub_idu`. + * Applies only if the base asset is a video. Maps to `ldu` in the URL. + */ + duration?: number | string; + + /** + * Specifies the end time (in seconds) for when the overlay should disappear from + * the base video. If both end and duration are provided, duration is ignored. + * Accepts a positive number up to two decimal places (e.g., `20` or `20.50`) and + * arithmetic expressions such as `bdu_mul_0.4` or `bdu_sub_idu`. Applies only if + * the base asset is a video. Maps to `leo` in the URL. + */ + end?: number | string; + + /** + * Specifies the start time (in seconds) for when the overlay should appear on the + * base video. Accepts a positive number up to two decimal places (e.g., `20` or + * `20.50`) and arithmetic expressions such as `bdu_mul_0.4` or `bdu_sub_idu`. + * Applies only if the base asset is a video. Maps to `lso` in the URL. + */ + start?: number | string; +} + +/** + * Resulting set of attributes suitable for an HTML `` element. Useful for + * enabling responsive image loading with `srcSet` and `sizes`. + */ +export interface ResponsiveImageAttributes { + /** + * URL for the _largest_ candidate (assigned to plain `src`). + */ + src: string; + + /** + * `sizes` returned (or synthesised as `100vw`). The value for the HTML `sizes` + * attribute. + */ + sizes?: string; + + /** + * Candidate set with `w` or `x` descriptors. Multiple image URLs separated by + * commas, each with a descriptor. + */ + srcSet?: string; + + /** + * Width as a number (if `width` was provided in the input options). + */ + width?: number; +} + +/** + * Saved extension object containing extension configuration. + */ +export interface SavedExtension { + /** + * Unique identifier of the saved extension. + */ + id?: string; + + /** + * Configuration object for an extension (base extensions only, not saved extension + * references). + */ + config?: ExtensionConfig; + + /** + * Timestamp when the saved extension was created. + */ + createdAt?: string; + + /** + * Description of the saved extension. + */ + description?: string; + + /** + * Name of the saved extension. + */ + name?: string; + + /** + * Timestamp when the saved extension was last updated. + */ + updatedAt?: string; +} + +export interface SolidColorOverlay extends BaseOverlay { + /** + * Specifies the color of the block using an RGB hex code (e.g., `FF0000`), an RGBA + * code (e.g., `FFAABB50`), or a color name (e.g., `red`). If an 8-character value + * is provided, the last two characters represent the opacity level (from `00` for + * 0.00 to `99` for 0.99). + */ + color: string; + + type: 'solidColor'; + + /** + * Control width and height of the solid color overlay. Supported transformations + * depend on the base/parent asset. See overlays on + * [Images](https://imagekit.io/docs/add-overlays-on-images#apply-transformation-on-solid-color-overlay) + * and + * [Videos](https://imagekit.io/docs/add-overlays-on-videos#apply-transformations-on-solid-color-block-overlay). + */ + transformation?: Array; +} + +export interface SolidColorOverlayTransformation { + /** + * Specifies the transparency level of the overlaid solid color layer. Supports + * integers from `1` to `9`. + */ + alpha?: number; + + /** + * Specifies the background color of the solid color overlay. Accepts an RGB hex + * code (e.g., `FF0000`), an RGBA code (e.g., `FFAABB50`), or a color name. + */ + background?: string; + + /** + * Creates a linear gradient with two colors. Pass `true` for a default gradient, + * or provide a string for a custom gradient. Only works if the base asset is an + * image. See + * [gradient](https://imagekit.io/docs/effects-and-enhancements#gradient---e-gradient). + */ + gradient?: true | string; + + /** + * Controls the height of the solid color overlay. Accepts a numeric value or an + * arithmetic expression. Learn about + * [arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + */ + height?: number | string; + + /** + * Specifies the corner radius of the solid color overlay. + * + * - Single value (positive integer): Applied to all corners (e.g., `20`). + * - `max`: Creates a circular or oval shape. + * - Per-corner array: Provide four underscore-separated values representing + * top-left, top-right, bottom-right, and bottom-left corners respectively (e.g., + * `10_20_30_40`). See + * [Radius](https://imagekit.io/docs/effects-and-enhancements#radius---r). + */ + radius?: number | 'max' | string; + + /** + * Controls the width of the solid color overlay. Accepts a numeric value or an + * arithmetic expression (e.g., `bw_mul_0.2` or `bh_div_2`). Learn about + * [arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + */ + width?: number | string; +} + +/** + * Options for generating ImageKit URLs with transformations. See the + * [Transformations guide](https://imagekit.io/docs/transformations). + */ +export interface SrcOptions { + /** + * Accepts a relative or absolute path of the resource. If a relative path is + * provided, it is appended to the `urlEndpoint`. If an absolute path is provided, + * `urlEndpoint` is ignored. + */ + src: string; + + /** + * Get your urlEndpoint from the + * [ImageKit dashboard](https://imagekit.io/dashboard/url-endpoints). + */ + urlEndpoint: string; + + /** + * These are additional query parameters that you want to add to the final URL. + * They can be any query parameters and not necessarily related to ImageKit. This + * is especially useful if you want to add a versioning parameter to your URLs. + */ + queryParameters?: { [key: string]: string | number }; + + /** + * An array of objects specifying the transformations to be applied in the URL. If + * more than one transformation is specified, they are applied in the order they + * are specified as chained transformations. See + * [Chained transformations](https://imagekit.io/docs/transformations#chained-transformations). + */ + transformation?: Array; + + /** + * By default, the transformation string is added as a query parameter in the URL, + * e.g., `?tr=w-100,h-100`. If you want to add the transformation string in the + * path of the URL, set this to `path`. Learn more in the + * [Transformations guide](https://imagekit.io/docs/transformations). + */ + transformationPosition?: TransformationPosition; +} + +/** + * Available streaming resolutions for + * [adaptive bitrate streaming](https://imagekit.io/docs/adaptive-bitrate-streaming) + */ +export type StreamingResolution = '240' | '360' | '480' | '720' | '1080' | '1440' | '2160'; + +export interface SubtitleOverlay extends BaseOverlay { + /** + * Specifies the relative path to the subtitle file used as an overlay. + */ + input: string; + + type: 'subtitle'; + + /** + * The input path can be included in the layer as either `i-{input}` or + * `ie-{base64_encoded_input}`. By default, the SDK determines the appropriate + * format automatically. To always use base64 encoding (`ie-{base64}`), set this + * parameter to `base64`. To always use plain text (`i-{input}`), set it to + * `plain`. + * + * Regardless of the encoding method: + * + * - Leading and trailing slashes are removed. + * - Remaining slashes within the path are replaced with `@@` when using plain + * text. + */ + encoding?: 'auto' | 'plain' | 'base64'; + + /** + * Control styling of the subtitle. See + * [Styling subtitles](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer). + */ + transformation?: Array; +} + +/** + * Subtitle styling options. + * [Learn more](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + * from the docs. + */ +export interface SubtitleOverlayTransformation { + /** + * Specifies the subtitle background color using a standard color name, an RGB + * color code (e.g., FF0000), or an RGBA color code (e.g., FFAABB50). + * + * [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + */ + background?: string; + + /** + * Sets the font color of the subtitle text using a standard color name, an RGB + * color code (e.g., FF0000), or an RGBA color code (e.g., FFAABB50). + * + * [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + */ + color?: string; + + /** + * Sets the font family of subtitle text. Refer to the + * [supported fonts documented](https://imagekit.io/docs/add-overlays-on-images#supported-text-font-list) + * in the ImageKit transformations guide. + */ + fontFamily?: string; + + /** + * Sets the font outline of the subtitle text. Requires the outline width (an + * integer) and the outline color (as an RGB color code, RGBA color code, or + * standard web color name) separated by an underscore. Example: `fol-2_blue` + * (outline width of 2px and outline color blue), `fol-2_A1CCDD` (outline width of + * 2px and outline color `#A1CCDD`) and `fol-2_A1CCDD50` (outline width of 2px and + * outline color `#A1CCDD` at 50% opacity). + * + * [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + */ + fontOutline?: string; + + /** + * Sets the font shadow for the subtitle text. Requires the shadow color (as an RGB + * color code, RGBA color code, or standard web color name) and shadow indent (an + * integer) separated by an underscore. Example: `fsh-blue_2` (shadow color blue, + * indent of 2px), `fsh-A1CCDD_3` (shadow color `#A1CCDD`, indent of 3px), + * `fsh-A1CCDD50_3` (shadow color `#A1CCDD` at 50% opacity, indent of 3px). + * + * [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + */ + fontShadow?: string; + + /** + * Sets the font size of subtitle text. + * + * [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + */ + fontSize?: number; + + /** + * Sets the typography style of the subtitle text. Supports values are `b` for + * bold, `i` for italics, and `b_i` for bold with italics. + * + * [Subtitle styling options](https://imagekit.io/docs/add-overlays-on-videos#styling-controls-for-subtitles-layer) + */ + typography?: 'b' | 'i' | 'b_i'; +} + +export interface TextOverlay extends BaseOverlay { + /** + * Specifies the text to be displayed in the overlay. The SDK automatically handles + * special characters and encoding. + */ + text: string; + + type: 'text'; + + /** + * Text can be included in the layer as either `i-{input}` (plain text) or + * `ie-{base64_encoded_input}` (base64). By default, the SDK selects the + * appropriate format based on the input text. To always use base64 + * (`ie-{base64}`), set this parameter to `base64`. To always use plain text + * (`i-{input}`), set it to `plain`. + * + * Regardless of the encoding method, the input text is always percent-encoded to + * ensure it is URL-safe. + */ + encoding?: 'auto' | 'plain' | 'base64'; + + /** + * Control styling of the text overlay. See + * [Text overlays](https://imagekit.io/docs/add-overlays-on-images#text-overlay). + */ + transformation?: Array; +} + +export interface TextOverlayTransformation { + /** + * Specifies the transparency level of the text overlay. Accepts integers from `1` + * to `9`. + */ + alpha?: number; + + /** + * Specifies the background color of the text overlay. Accepts an RGB hex code, an + * RGBA code, or a color name. + */ + background?: string; + + /** + * Flip/mirror the text horizontally, vertically, or in both directions. Acceptable + * values: `h` (horizontal), `v` (vertical), `h_v` (horizontal and vertical), or + * `v_h`. + */ + flip?: 'h' | 'v' | 'h_v' | 'v_h'; + + /** + * Specifies the font color of the overlaid text. Accepts an RGB hex code (e.g., + * `FF0000`), an RGBA code (e.g., `FFAABB50`), or a color name. + */ + fontColor?: string; + + /** + * Specifies the font family of the overlaid text. Choose from the supported fonts + * list or use a custom font. See + * [Supported fonts](https://imagekit.io/docs/add-overlays-on-images#supported-text-font-list) + * and + * [Custom font](https://imagekit.io/docs/add-overlays-on-images#change-font-family-in-text-overlay). + */ + fontFamily?: string; + + /** + * Specifies the font size of the overlaid text. Accepts a numeric value or an + * arithmetic expression. + */ + fontSize?: number | string; + + /** + * Specifies the inner alignment of the text when width is more than the text + * length. + */ + innerAlignment?: 'left' | 'right' | 'center'; + + /** + * Specifies the line height for multi-line text overlays. It will come into effect + * only if the text wraps over multiple lines. Accepts either an integer value or + * an arithmetic expression. + */ + lineHeight?: number | string; + + /** + * Specifies the padding around the overlaid text. Can be provided as a single + * positive integer or multiple values separated by underscores (following CSS + * shorthand order). Arithmetic expressions are also accepted. + */ + padding?: number | string; + + /** + * Specifies the corner radius: + * + * - Single value (positive integer): Applied to all corners (e.g., `20`). + * - `max`: Creates a circular or oval shape. + * - Per-corner array: Provide four underscore-separated values representing + * top-left, top-right, bottom-right, and bottom-left corners respectively (e.g., + * `10_20_30_40`). See + * [Radius](https://imagekit.io/docs/effects-and-enhancements#radius---r). + */ + radius?: number | 'max' | string; + + /** + * Specifies the rotation angle of the text overlay. Accepts a numeric value for + * clockwise rotation or a string prefixed with "N" for counter-clockwise rotation. + */ + rotation?: number | string; + + /** + * Specifies the typography style of the text. Supported values: + * + * - Single styles: `b` (bold), `i` (italic), `strikethrough`. + * - Combinations: Any combination separated by underscores, e.g., `b_i`, + * `b_i_strikethrough`. + */ + typography?: string; + + /** + * Specifies the maximum width (in pixels) of the overlaid text. The text wraps + * automatically, and arithmetic expressions (e.g., `bw_mul_0.2` or `bh_div_2`) are + * supported. Useful when used in conjunction with the `background`. Learn about + * [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + */ + width?: number | string; +} + +/** + * The SDK provides easy-to-use names for transformations. These names are + * converted to the corresponding transformation string before being added to the + * URL. SDKs are updated regularly to support new transformations. If you want to + * use a transformation that is not supported by the SDK, You can use the `raw` + * parameter to pass the transformation string directly. See the + * [Transformations documentation](https://imagekit.io/docs/transformations). + */ +export interface Transformation { + /** + * Uses AI to change the background. Provide a text prompt or a base64-encoded + * prompt, e.g., `prompt-snow road` or `prompte-[urlencoded_base64_encoded_text]`. + * Not supported inside overlay. See + * [AI Change Background](https://imagekit.io/docs/ai-transformations#change-background-e-changebg). + */ + aiChangeBackground?: string; + + /** + * Adds an AI-based drop shadow around a foreground object on a transparent or + * removed background. Optionally, control the direction, elevation, and saturation + * of the light source (e.g., `az-45` to change light direction). Pass `true` for + * the default drop shadow, or provide a string for a custom drop shadow. Supported + * inside overlay. See + * [AI Drop Shadow](https://imagekit.io/docs/ai-transformations#ai-drop-shadow-e-dropshadow). + */ + aiDropShadow?: true | string; + + /** + * Uses AI to edit images based on a text prompt. Provide a text prompt or a + * base64-encoded prompt, e.g., `prompt-snow road` or + * `prompte-[urlencoded_base64_encoded_text]`. Not supported inside overlay. + * See [AI Edit](https://imagekit.io/docs/ai-transformations#edit-image-e-edit). + */ + aiEdit?: string; + + /** + * Applies ImageKit's in-house background removal. Supported inside overlay. See + * [AI Background Removal](https://imagekit.io/docs/ai-transformations#imagekit-background-removal-e-bgremove). + */ + aiRemoveBackground?: true; + + /** + * Uses third-party background removal. Note: It is recommended to use + * aiRemoveBackground, ImageKit's in-house solution, which is more cost-effective. + * Supported inside overlay. See + * [External Background Removal](https://imagekit.io/docs/ai-transformations#background-removal-e-removedotbg). + */ + aiRemoveBackgroundExternal?: true; + + /** + * Performs AI-based retouching to improve faces or product shots. Not supported + * inside overlay. See + * [AI Retouch](https://imagekit.io/docs/ai-transformations#retouch-e-retouch). + */ + aiRetouch?: true; + + /** + * Upscales images beyond their original dimensions using AI. Not supported inside + * overlay. See + * [AI Upscale](https://imagekit.io/docs/ai-transformations#upscale-e-upscale). + */ + aiUpscale?: true; + + /** + * Generates a variation of an image using AI. This produces a new image with + * slight variations from the original, such as changes in color, texture, and + * other visual elements, while preserving the structure and essence of the + * original image. Not supported inside overlay. See + * [AI Generate Variations](https://imagekit.io/docs/ai-transformations#generate-variations-of-an-image-e-genvar). + */ + aiVariation?: true; + + /** + * Specifies the aspect ratio for the output, e.g., "ar-4-3". Typically used with + * either width or height (but not both). For example: aspectRatio = `4:3`, `4_3`, + * or an expression like `iar_div_2`. See + * [Image resize and crop – Aspect ratio](https://imagekit.io/docs/image-resize-and-crop#aspect-ratio---ar). + */ + aspectRatio?: number | string; + + /** + * Specifies the audio codec, e.g., `aac`, `opus`, or `none`. See + * [Audio codec](https://imagekit.io/docs/video-optimization#audio-codec---ac). + */ + audioCodec?: 'aac' | 'opus' | 'none'; + + /** + * Specifies the background to be used in conjunction with certain cropping + * strategies when resizing an image. + * + * - A solid color: e.g., `red`, `F3F3F3`, `AAFF0010`. See + * [Solid color background](https://imagekit.io/docs/effects-and-enhancements#solid-color-background). + * - Dominant color: `dominant` extracts the dominant color from the image. See + * [Dominant color background](https://imagekit.io/docs/effects-and-enhancements#dominant-color-background). + * - Gradient: `gradient_dominant` or `gradient_dominant_2` creates a gradient + * using the dominant colors. Optionally specify palette size (2 or 4), e.g., + * `gradient_dominant_4`. See + * [Gradient background](https://imagekit.io/docs/effects-and-enhancements#gradient-background). + * - A blurred background: e.g., `blurred`, `blurred_25_N15`, etc. See + * [Blurred background](https://imagekit.io/docs/effects-and-enhancements#blurred-background). + * - Expand the image boundaries using generative fill: `genfill`. Not supported + * inside overlay. Optionally, control the background scene by passing a text + * prompt: `genfill[:-prompt-${text}]` or + * `genfill[:-prompte-${urlencoded_base64_encoded_text}]`. See + * [Generative fill background](https://imagekit.io/docs/ai-transformations#generative-fill-bg-genfill). + */ + background?: string; + + /** + * Specifies the Gaussian blur level. Accepts an integer value between 1 and 100, + * or an expression like `bl-10`. See + * [Blur](https://imagekit.io/docs/effects-and-enhancements#blur---bl). + */ + blur?: number; + + /** + * Adds a border to the output media. Accepts a string in the format + * `_` (e.g., `5_FFF000` for a 5px yellow border), or an + * expression like `ih_div_20_FF00FF`. See + * [Border](https://imagekit.io/docs/effects-and-enhancements#border---b). + */ + border?: string; + + /** + * Applies a color tint to the image. Accepts color and intensity as optional + * parameters. + * + * - `co-color` - Color to apply (e.g., `red`, `blue`, `FF0022`). Default is gray + * color. + * - `in-intensity` - Intensity of the color (0-100). Default is 35. See + * [Colorize](https://imagekit.io/docs/effects-and-enhancements#colorize---e-colorize). + */ + colorize?: string; + + /** + * Indicates whether the output image should retain the original color profile. See + * [Color profile](https://imagekit.io/docs/image-optimization#color-profile---cp). + */ + colorProfile?: boolean; + + /** + * Replaces colors in the image. Supports three formats: + * + * - `toColor` - Replace dominant color with the specified color. + * - `toColor_tolerance` - Replace dominant color with specified tolerance (0-100). + * - `toColor_tolerance_fromColor` - Replace a specific color with another within + * tolerance range. Colors can be hex codes (e.g., `FF0022`) or names (e.g., + * `red`, `blue`). See + * [Color replacement](https://imagekit.io/docs/effects-and-enhancements#color-replace---cr). + */ + colorReplace?: string; + + /** + * Automatically enhances the contrast of an image (contrast stretch). See + * [Contrast Stretch](https://imagekit.io/docs/effects-and-enhancements#contrast-stretch---e-contrast). + */ + contrastStretch?: true; + + /** + * Crop modes for image resizing. See + * [Crop modes & focus](https://imagekit.io/docs/image-resize-and-crop#crop-crop-modes--focus). + */ + crop?: 'force' | 'at_max' | 'at_max_enlarge' | 'at_least' | 'maintain_ratio' | 'maintain_ratio_no_enlarge'; + + /** + * Additional crop modes for image resizing. See + * [Crop modes & focus](https://imagekit.io/docs/image-resize-and-crop#crop-crop-modes--focus). + */ + cropMode?: 'pad_resize' | 'extract' | 'pad_extract' | 'pad_resize_no_enlarge' | 'pad_extract_no_shrink'; + + /** + * Specifies a fallback image if the resource is not found, e.g., a URL or file + * path. See + * [Default image](https://imagekit.io/docs/image-transformation#default-image---di). + */ + defaultImage?: string; + + /** + * Distorts the shape of an image. Supports two modes: + * + * - Perspective distortion: `p-x1_y1_x2_y2_x3_y3_x4_y4` changes the position of + * the four corners starting clockwise from top-left. + * - Arc distortion: `a-degrees` curves the image upwards (positive values) or + * downwards (negative values). See + * [Distort effect](https://imagekit.io/docs/effects-and-enhancements#distort---e-distort). + */ + distort?: string; + + /** + * Accepts values between 0.1 and 5, or `auto` for automatic device pixel ratio + * (DPR) calculation. Also accepts arithmetic expressions. + * + * - Learn about + * [Arithmetic expressions](https://imagekit.io/docs/arithmetic-expressions-in-transformations). + * - See [DPR](https://imagekit.io/docs/image-resize-and-crop#dpr---dpr). + */ + dpr?: number | string; + + /** + * Specifies the duration (in seconds) for trimming videos, e.g., `5` or `10.5`. + * Typically used with startOffset to indicate the length from the start offset. + * Arithmetic expressions are supported. See + * [Trim videos – Duration](https://imagekit.io/docs/trim-videos#duration---du). + */ + duration?: number | string; + + /** + * Specifies the end offset (in seconds) for trimming videos, e.g., `5` or `10.5`. + * Typically used with startOffset to define a time window. Arithmetic expressions + * are supported. See + * [Trim videos – End offset](https://imagekit.io/docs/trim-videos#end-offset---eo). + */ + endOffset?: number | string; + + /** + * Flips or mirrors an image either horizontally, vertically, or both. Acceptable + * values: `h` (horizontal), `v` (vertical), `h_v` (horizontal and vertical), or + * `v_h`. See [Flip](https://imagekit.io/docs/effects-and-enhancements#flip---fl). + */ + flip?: 'h' | 'v' | 'h_v' | 'v_h'; + + /** + * Refines padding and cropping behavior for pad resize, maintain ratio, and + * extract crop modes. Supports manual positions and coordinate-based focus. With + * AI-based cropping, you can automatically keep key subjects in frame—such as + * faces or detected objects (e.g., `fo-face`, `fo-person`, `fo-car`)— while + * resizing. + * + * - See [Focus](https://imagekit.io/docs/image-resize-and-crop#focus---fo). + * - [Object aware cropping](https://imagekit.io/docs/image-resize-and-crop#object-aware-cropping---fo-object-name) + */ + focus?: string; + + /** + * Specifies the output format for images or videos, e.g., `jpg`, `png`, `webp`, + * `mp4`, or `auto`. You can also pass `orig` for images to return the original + * format. ImageKit automatically delivers images and videos in the optimal format + * based on device support unless overridden by the dashboard settings or the + * format parameter. See + * [Image format](https://imagekit.io/docs/image-optimization#format---f) and + * [Video format](https://imagekit.io/docs/video-optimization#format---f). + */ + format?: 'auto' | 'webp' | 'jpg' | 'jpeg' | 'png' | 'gif' | 'svg' | 'mp4' | 'webm' | 'avif' | 'orig'; + + /** + * Creates a linear gradient with two colors. Pass `true` for a default gradient, + * or provide a string for a custom gradient. See + * [Gradient](https://imagekit.io/docs/effects-and-enhancements#gradient---e-gradient). + */ + gradient?: true | string; + + /** + * Enables a grayscale effect for images. See + * [Grayscale](https://imagekit.io/docs/effects-and-enhancements#grayscale---e-grayscale). + */ + grayscale?: true; + + /** + * Specifies the height of the output. If a value between 0 and 1 is provided, it + * is treated as a percentage (e.g., `0.5` represents 50% of the original height). + * You can also supply arithmetic expressions (e.g., `ih_mul_0.5`). Height + * transformation – + * [Images](https://imagekit.io/docs/image-resize-and-crop#height---h) · + * [Videos](https://imagekit.io/docs/video-resize-and-crop#height---h) + */ + height?: number | string; + + /** + * Specifies whether the output image (in JPEG or PNG) should be compressed + * losslessly. See + * [Lossless compression](https://imagekit.io/docs/image-optimization#lossless-webp-and-png---lo). + */ + lossless?: boolean; + + /** + * By default, ImageKit removes all metadata during automatic image compression. + * Set this to true to preserve metadata. See + * [Image metadata](https://imagekit.io/docs/image-optimization#image-metadata---md). + */ + metadata?: boolean; + + /** + * Named transformation reference. See + * [Named transformations](https://imagekit.io/docs/transformations#named-transformations). + */ + named?: string; + + /** + * Specifies the opacity level of the output image. See + * [Opacity](https://imagekit.io/docs/effects-and-enhancements#opacity---o). + */ + opacity?: number; + + /** + * If set to true, serves the original file without applying any transformations. + * See + * [Deliver original file as-is](https://imagekit.io/docs/core-delivery-features#deliver-original-file-as-is---orig-true). + */ + original?: boolean; + + /** + * Specifies an overlay to be applied on the parent image or video. ImageKit + * supports overlays including images, text, videos, subtitles, and solid colors. + * See + * [Overlay using layers](https://imagekit.io/docs/transformations#overlay-using-layers). + */ + overlay?: Overlay; + + /** + * Extracts a specific page or frame from multi-page or layered files (PDF, PSD, + * AI). For example, specify by number (e.g., `2`), a range (e.g., `3-4` for the + * 2nd and 3rd layers), or by name (e.g., `name-layer-4` for a PSD layer). See + * [Thumbnail extraction](https://imagekit.io/docs/vector-and-animated-images#get-thumbnail-from-psd-pdf-ai-eps-and-animated-files). + */ + page?: number | string; + + /** + * Specifies whether the output JPEG image should be rendered progressively. + * Progressive loading begins with a low-quality, pixelated version of the full + * image, which gradually improves to provide a faster perceived load time. See + * [Progressive images](https://imagekit.io/docs/image-optimization#progressive-image---pr). + */ + progressive?: boolean; + + /** + * Specifies the quality of the output image for lossy formats such as JPEG, WebP, + * and AVIF. A higher quality value results in a larger file size with better + * quality, while a lower value produces a smaller file size with reduced quality. + * See [Quality](https://imagekit.io/docs/image-optimization#quality---q). + */ + quality?: number; + + /** + * Specifies the corner radius for rounded corners. + * + * - Single value (positive integer): Applied to all corners (e.g., `20`). + * - `max`: Creates a circular or oval shape. + * - Per-corner array: Provide four underscore-separated values representing + * top-left, top-right, bottom-right, and bottom-left corners respectively (e.g., + * `10_20_30_40`). See + * [Radius](https://imagekit.io/docs/effects-and-enhancements#radius---r). + */ + radius?: number | 'max' | string; + + /** + * Pass any transformation not directly supported by the SDK. This transformation + * string is appended to the URL as provided. + */ + raw?: string; + + /** + * Specifies the rotation angle in degrees. Positive values rotate the image + * clockwise; you can also use, for example, `N40` for counterclockwise rotation or + * `auto` to use the orientation specified in the image's EXIF data. For videos, + * only the following values are supported: 0, 90, 180, 270, or 360. See + * [Rotate](https://imagekit.io/docs/effects-and-enhancements#rotate---rt). + */ + rotation?: number | string; + + /** + * Adds a shadow beneath solid objects in an image with a transparent background. + * For AI-based drop shadows, refer to aiDropShadow. Pass `true` for a default + * shadow, or provide a string for a custom shadow. See + * [Shadow](https://imagekit.io/docs/effects-and-enhancements#shadow---e-shadow). + */ + shadow?: true | string; + + /** + * Sharpens the input image, highlighting edges and finer details. Pass `true` for + * default sharpening, or provide a numeric value for custom sharpening. See + * [Sharpen](https://imagekit.io/docs/effects-and-enhancements#sharpen---e-sharpen). + */ + sharpen?: true | number; + + /** + * Specifies the start offset (in seconds) for trimming videos, e.g., `5` or + * `10.5`. Arithmetic expressions are also supported. See + * [Trim videos – Start offset](https://imagekit.io/docs/trim-videos#start-offset---so). + */ + startOffset?: number | string; + + /** + * An array of resolutions for adaptive bitrate streaming, e.g., [`240`, `360`, + * `480`, `720`, `1080`]. See + * [Adaptive Bitrate Streaming](https://imagekit.io/docs/adaptive-bitrate-streaming). + */ + streamingResolutions?: Array; + + /** + * Useful for images with a solid or nearly solid background and a central object. + * This parameter trims the background, leaving only the central object in the + * output image. See + * [Trim edges](https://imagekit.io/docs/effects-and-enhancements#trim-edges---t). + */ + trim?: true | number; + + /** + * Applies Unsharp Masking (USM), an image sharpening technique. Pass `true` for a + * default unsharp mask, or provide a string for a custom unsharp mask. See + * [Unsharp Mask](https://imagekit.io/docs/effects-and-enhancements#unsharp-mask---e-usm). + */ + unsharpMask?: true | string; + + /** + * Specifies the video codec, e.g., `h264`, `vp9`, `av1`, or `none`. See + * [Video codec](https://imagekit.io/docs/video-optimization#video-codec---vc). + */ + videoCodec?: 'h264' | 'vp9' | 'av1' | 'none'; + + /** + * Specifies the width of the output. If a value between 0 and 1 is provided, it is + * treated as a percentage (e.g., `0.4` represents 40% of the original width). You + * can also supply arithmetic expressions (e.g., `iw_div_2`). Width transformation + * – [Images](https://imagekit.io/docs/image-resize-and-crop#width---w) · + * [Videos](https://imagekit.io/docs/video-resize-and-crop#width---w) + */ + width?: number | string; + + /** + * Focus using cropped image coordinates - X coordinate. See + * [Focus using cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). + */ + x?: number | string; + + /** + * Focus using cropped image coordinates - X center coordinate. See + * [Focus using cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). + */ + xCenter?: number | string; + + /** + * Focus using cropped image coordinates - Y coordinate. See + * [Focus using cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). + */ + y?: number | string; + + /** + * Focus using cropped image coordinates - Y center coordinate. See + * [Focus using cropped coordinates](https://imagekit.io/docs/image-resize-and-crop#example---focus-using-cropped-image-coordinates). + */ + yCenter?: number | string; + + /** + * Accepts a numeric value that determines how much to zoom in or out of the + * cropped area. It should be used in conjunction with fo-face or fo-. + * See [Zoom](https://imagekit.io/docs/image-resize-and-crop#zoom---z). + */ + zoom?: number; +} + +/** + * By default, the transformation string is added as a query parameter in the URL, + * e.g., `?tr=w-100,h-100`. If you want to add the transformation string in the + * path of the URL, set this to `path`. Learn more in the + * [Transformations guide](https://imagekit.io/docs/transformations). + */ +export type TransformationPosition = 'path' | 'query'; + +export interface VideoOverlay extends BaseOverlay { + /** + * Specifies the relative path to the video used as an overlay. + */ + input: string; + + type: 'video'; + + /** + * The input path can be included in the layer as either `i-{input}` or + * `ie-{base64_encoded_input}`. By default, the SDK determines the appropriate + * format automatically. To always use base64 encoding (`ie-{base64}`), set this + * parameter to `base64`. To always use plain text (`i-{input}`), set it to + * `plain`. + * + * Regardless of the encoding method: + * + * - Leading and trailing slashes are removed. + * - Remaining slashes within the path are replaced with `@@` when using plain + * text. + */ + encoding?: 'auto' | 'plain' | 'base64'; + + /** + * Array of transformation to be applied to the overlay video. Except + * `streamingResolutions`, all other video transformations are supported. See + * [Video transformations](https://imagekit.io/docs/video-transformation). + */ + transformation?: Array; +} diff --git a/src/responsive.ts b/src/responsive.ts new file mode 100644 index 0000000..73286ba --- /dev/null +++ b/src/responsive.ts @@ -0,0 +1,107 @@ +import type { ResponsiveImageAttributes, GetImageAttributesOptions } from './interfaces' +import { buildSrc } from './url' + +/* Default break‑point pools */ +const DEFAULT_DEVICE_BREAKPOINTS = [640, 750, 828, 1080, 1200, 1920, 2048, 3840] as const +const DEFAULT_IMAGE_BREAKPOINTS = [16, 32, 48, 64, 96, 128, 256, 384] as const + +/** + * Generates a responsive image URL, `srcSet`, and `sizes` attributes + * based on the input options such as `width`, `sizes`, and breakpoints. + */ +export function getResponsiveImageAttributes( + opts: GetImageAttributesOptions +): ResponsiveImageAttributes { + const { + src, + urlEndpoint, + transformation = [], + queryParameters, + transformationPosition, + sizes, + width, + deviceBreakpoints = DEFAULT_DEVICE_BREAKPOINTS as unknown as number[], + imageBreakpoints = DEFAULT_IMAGE_BREAKPOINTS as unknown as number[], + } = opts + + const sortedDeviceBreakpoints = [...deviceBreakpoints].sort((a, b) => a - b); + const sortedImageBreakpoints = [...imageBreakpoints].sort((a, b) => a - b); + const allBreakpoints = [...sortedImageBreakpoints, ...sortedDeviceBreakpoints].sort((a, b) => a - b); + + const { candidates, descriptorKind } = computeCandidateWidths({ + allBreakpoints, + deviceBreakpoints: sortedDeviceBreakpoints, + explicitWidth: width, + sizesAttr: sizes, + }) + + /* helper to build a single ImageKit URL */ + const buildURL = (w: number) => + buildSrc({ + src, + urlEndpoint, + queryParameters, + transformationPosition, + transformation: [ + ...transformation, + { width: w, crop: 'at_max' }, // never upscale beyond original + ], + }) + + /* build srcSet */ + const srcSet = + candidates + .map((w, i) => `${buildURL(w)} ${descriptorKind === 'w' ? w : i + 1}${descriptorKind}`) + .join(', ') || undefined + + const finalSizes = sizes ?? (descriptorKind === 'w' ? '100vw' : undefined) + + return { + src: buildURL(candidates[candidates.length - 1]), // largest candidate + srcSet, + ...(finalSizes ? { sizes: finalSizes } : {}), // include only when defined + ...(width !== undefined ? { width } : {}), // include only when defined + } +} + +function computeCandidateWidths(params: { + allBreakpoints: number[] + deviceBreakpoints: number[] + explicitWidth?: number + sizesAttr?: string +}): { candidates: number[]; descriptorKind: 'w' | 'x' } { + const { allBreakpoints, deviceBreakpoints, explicitWidth, sizesAttr } = params + + // Strategy 1: Width-based srcSet (`w`) using viewport `vw` hints + if (sizesAttr) { + const vwTokens = sizesAttr.match(/(^|\s)(1?\d{1,2})vw/g) || [] + const vwPercents = vwTokens.map((t) => parseInt(t, 10)) + + if (vwPercents.length) { + const smallestRatio = Math.min(...vwPercents) / 100 + const minRequiredPx = deviceBreakpoints[0] * smallestRatio + return { + candidates: allBreakpoints.filter((w) => w >= minRequiredPx), + descriptorKind: 'w', + } + } + + // No usable `vw` found: fallback to all breakpoints + return { candidates: allBreakpoints, descriptorKind: 'w' } + } + + // Strategy 2: Fallback using explicit image width using device breakpoints + if (typeof explicitWidth !== 'number') { + return { candidates: deviceBreakpoints, descriptorKind: 'w' } + } + + // Strategy 3: Use 1x and 2x nearest breakpoints for `x` descriptor + const nearest = (t: number) => + allBreakpoints.find((n) => n >= t) || allBreakpoints[allBreakpoints.length - 1] + + const unique = Array.from( + new Set([nearest(explicitWidth), nearest(explicitWidth * 2)]), + ) + + return { candidates: unique, descriptorKind: 'x' } +} diff --git a/src/upload.ts b/src/upload.ts new file mode 100644 index 0000000..e5a8fea --- /dev/null +++ b/src/upload.ts @@ -0,0 +1,272 @@ +import errorMessages from "./constants/errorMessages"; +import type { ResponseMetadata, UploadOptions, UploadResponse } from "./interfaces"; + +/** + * Represents an error when a request to ImageKit is invalid. + */ +export class ImageKitInvalidRequestError extends Error { + /** + * Optional metadata about the response. It is only available if server returns a response. + */ + readonly $ResponseMetadata?: ResponseMetadata; + constructor(message: string, responseMetadata?: ResponseMetadata) { + super(message); + this.name = "ImageKitInvalidRequestError"; + this.$ResponseMetadata = responseMetadata; + } +} + +/** + * Represents an error when an upload operation is aborted. + */ +export class ImageKitAbortError extends Error { + /** + * The reason why the operation was aborted, which can be any JavaScript value. If not specified, the reason is set to "AbortError" DOMException. + */ + reason?: unknown; + constructor(message: string, reason?: unknown) { + super(message); + this.name = "ImageKitAbortError"; + this.reason = reason; + } +} + +/** + * Represents a network error during an upload operation to ImageKit. + */ +export class ImageKitUploadNetworkError extends Error { + constructor(message: string) { + super(message); + this.name = "ImageKitUploadNetworkError"; + } +} + +/** + * Represents a server error from ImageKit during an upload operation. + */ +export class ImageKitServerError extends Error { + /** + * Optional metadata about the response. It is only available if server returns a response. + */ + readonly $ResponseMetadata?: ResponseMetadata; + constructor(message: string, responseMetadata?: ResponseMetadata) { + super(message); + this.name = "ImageKitServerError"; + this.$ResponseMetadata = responseMetadata; + } +} + +/** + * Uploads a file to ImageKit with the given upload options. This function uses V1 API, check the [API docs](https://imagekit.io/docs/api-reference/upload-file/upload-file) for more details. + * + * @throws {ImageKitInvalidRequestError} If the request is invalid. + * @throws {ImageKitAbortError} If the request is aborted. + * @throws {ImageKitUploadNetworkError} If there is a network error. + * @throws {ImageKitServerError} If there is a server error. + * + * @param {UploadOptions} uploadOptions - The options for uploading the file. + * @returns {Promise} A Promise resolving to a successful UploadResponse. + */ +export const upload = (uploadOptions: UploadOptions): Promise => { + if(!uploadOptions) { + return Promise.reject(new ImageKitInvalidRequestError("Invalid options provided for upload")); + } + return new Promise((resolve, reject) => { + const { xhr: userProvidedXHR } = uploadOptions || {}; + delete uploadOptions.xhr; + const xhr = userProvidedXHR || new XMLHttpRequest(); + + if (!uploadOptions.file) { + return reject(new ImageKitInvalidRequestError(errorMessages.MISSING_UPLOAD_FILE_PARAMETER.message)); + } + + if (!uploadOptions.fileName) { + return reject(new ImageKitInvalidRequestError(errorMessages.MISSING_UPLOAD_FILENAME_PARAMETER.message)); + } + + if (!uploadOptions.publicKey || uploadOptions.publicKey.length === 0) { + return reject(new ImageKitInvalidRequestError(errorMessages.MISSING_PUBLIC_KEY.message)); + } + + if (!uploadOptions.token) { + return reject(new ImageKitInvalidRequestError(errorMessages.MISSING_TOKEN.message)); + } + + if (!uploadOptions.signature) { + return reject(new ImageKitInvalidRequestError(errorMessages.MISSING_SIGNATURE.message)); + } + + if (!uploadOptions.expire) { + return reject(new ImageKitInvalidRequestError(errorMessages.MISSING_EXPIRE.message)); + } + + if (uploadOptions.transformation) { + if (!(Object.keys(uploadOptions.transformation).includes("pre") || Object.keys(uploadOptions.transformation).includes("post"))) { + return reject(new ImageKitInvalidRequestError(errorMessages.INVALID_TRANSFORMATION.message)); + } + if (Object.keys(uploadOptions.transformation).includes("pre") && !uploadOptions.transformation.pre) { + return reject(new ImageKitInvalidRequestError(errorMessages.INVALID_PRE_TRANSFORMATION.message)); + } + if (Object.keys(uploadOptions.transformation).includes("post")) { + if (Array.isArray(uploadOptions.transformation.post)) { + for (let transformation of uploadOptions.transformation.post) { + if (transformation.type === "abs" && !(transformation.protocol || transformation.value)) { + return reject(new ImageKitInvalidRequestError(errorMessages.INVALID_POST_TRANSFORMATION.message)); + } else if (transformation.type === "transformation" && !transformation.value) { + return reject(new ImageKitInvalidRequestError(errorMessages.INVALID_POST_TRANSFORMATION.message)); + } + } + } else { + return reject(new ImageKitInvalidRequestError(errorMessages.INVALID_POST_TRANSFORMATION.message)); + } + } + } + + var formData = new FormData(); + let key: keyof typeof uploadOptions; + for (key in uploadOptions) { + if (key) { + if (key === "file" && typeof uploadOptions.file != "string") { + formData.set('file', uploadOptions.file, String(uploadOptions.fileName)); + } else if (key === "tags" && Array.isArray(uploadOptions.tags)) { + formData.set('tags', uploadOptions.tags.join(",")); + } else if (key === 'signature') { + formData.set("signature", uploadOptions.signature); + } else if (key === 'expire') { + formData.set("expire", String(uploadOptions.expire)); + } else if (key === 'token') { + formData.set("token", uploadOptions.token); + } else if (key === "responseFields" && Array.isArray(uploadOptions.responseFields)) { + formData.set('responseFields', uploadOptions.responseFields.join(",")); + } else if (key === "extensions" && Array.isArray(uploadOptions.extensions)) { + formData.set('extensions', JSON.stringify(uploadOptions.extensions)); + } else if (key === "customMetadata" && typeof uploadOptions.customMetadata === "object" && + !Array.isArray(uploadOptions.customMetadata) && uploadOptions.customMetadata !== null) { + formData.set('customMetadata', JSON.stringify(uploadOptions.customMetadata)); + } else if (key === "transformation" && typeof uploadOptions.transformation === "object" && + uploadOptions.transformation !== null) { + formData.set(key, JSON.stringify(uploadOptions.transformation)); + } else if (key === 'checks' && uploadOptions.checks) { + formData.set("checks", uploadOptions.checks); + } else if (uploadOptions[key] !== undefined) { + if (["onProgress", "abortSignal"].includes(key)) continue; + formData.set(key, String(uploadOptions[key])); + } + } + } + + if (uploadOptions.onProgress) { + xhr.upload.onprogress = function (event: ProgressEvent) { + if (uploadOptions.onProgress) uploadOptions.onProgress(event) + }; + } + + function onAbortHandler() { + xhr.abort(); + return reject(new ImageKitAbortError( + "Upload aborted", + uploadOptions.abortSignal?.reason + )); + } + + if (uploadOptions.abortSignal) { + if (uploadOptions.abortSignal.aborted) { + // If the signal is already aborted, return immediately with the reason + + return reject(new ImageKitAbortError( + "Upload aborted", + uploadOptions.abortSignal?.reason + )); + } + + // If the signal is not already aborted, add an event listener to abort the request when the signal is aborted + uploadOptions.abortSignal.addEventListener("abort", onAbortHandler); + + // On XHR completion (success, fail, or abort), remove just this abort handler + xhr.addEventListener("loadend", () => { + if (uploadOptions.abortSignal) { + uploadOptions.abortSignal.removeEventListener("abort", onAbortHandler); + } + }); + } + + xhr.open('POST', 'https://upload.imagekit.io/api/v1/files/upload'); + xhr.onerror = function (e) { + return reject(new ImageKitUploadNetworkError(errorMessages.UPLOAD_ENDPOINT_NETWORK_ERROR.message)); + } + xhr.onload = function () { + if (xhr.status >= 200 && xhr.status < 300) { + try { + var body = JSON.parse(xhr.responseText); + var uploadResponse = addResponseHeadersAndBody(body, xhr); + return resolve(uploadResponse); + } catch (ex: any) { + return reject(ex); + } + } else if (xhr.status >= 400 && xhr.status < 500) { + // Send ImageKitInvalidRequestError + try { + var body = JSON.parse(xhr.responseText); + return reject(new ImageKitInvalidRequestError( + body.message ?? "Invalid request. Please check the parameters.", + getResponseMetadata(xhr) + )); + } catch (ex: any) { + return reject(ex); + } + } else { + // Send ImageKitServerError + try { + var body = JSON.parse(xhr.responseText); + return reject(new ImageKitServerError( + body.message ?? "Server error occurred while uploading the file. This is rare and usually temporary.", + getResponseMetadata(xhr) + )); + } catch (ex: any) { + return reject(new ImageKitServerError( + "Server error occurred while uploading the file. This is rare and usually temporary.", + getResponseMetadata(xhr) + )); + } + } + }; + xhr.send(formData); + }); +}; + + +const addResponseHeadersAndBody = (body: any, xhr: XMLHttpRequest) => { + let response = { ...body }; + const responseMetadata = getResponseMetadata(xhr); + Object.defineProperty(response, "$ResponseMetadata", { + value: responseMetadata, + enumerable: false, + writable: false + }); + return response; +} + +const getResponseMetadata = (xhr: XMLHttpRequest): ResponseMetadata => { + const headers = getResponseHeaderMap(xhr); + const responseMetadata = { + statusCode: xhr.status, + headers: headers, + requestId: headers["x-request-id"] + } + return responseMetadata; +} + +function getResponseHeaderMap(xhr: XMLHttpRequest): Record { + const headers: Record = {}; + const responseHeaders = xhr.getAllResponseHeaders(); + if (Object.keys(responseHeaders).length) { + responseHeaders + .trim() + .split(/[\r\n]+/) + .map(value => value.split(/: /)) + .forEach(keyValue => { + headers[keyValue[0].trim().toLowerCase()] = keyValue[1].trim(); + }); + } + return headers; +} diff --git a/src/upload/index.ts b/src/upload/index.ts deleted file mode 100644 index 8fabb9b..0000000 --- a/src/upload/index.ts +++ /dev/null @@ -1,56 +0,0 @@ -import errorMessages from "../constants/errorMessages"; -import respond from "../utils/respond"; -import { request } from "../utils/request"; -import { ImageKitOptions, UploadOptions, UploadResponse } from "../interfaces"; - -export const upload = ( - xhr: XMLHttpRequest, - uploadOptions: UploadOptions, - options: ImageKitOptions, - callback?: (err: Error | null, response: UploadResponse | null) => void, -) => { - if (!uploadOptions.file) { - respond(true, errorMessages.MISSING_UPLOAD_FILE_PARAMETER, callback); - return; - } - - if (!uploadOptions.fileName) { - respond(true, errorMessages.MISSING_UPLOAD_FILENAME_PARAMETER, callback); - return; - } - - if (!options.authenticationEndpoint) { - respond(true, errorMessages.MISSING_AUTHENTICATION_ENDPOINT, callback); - return; - } - - if (!options.publicKey) { - respond(true, errorMessages.MISSING_PUBLIC_KEY, callback); - return; - } - - var formData = new FormData(); - let key: keyof typeof uploadOptions; - for (key in uploadOptions) { - if (key) { - if (key === "file" && typeof uploadOptions.file != "string") { - formData.append('file', uploadOptions.file, String(uploadOptions.fileName)); - } else if (key === "tags" && Array.isArray(uploadOptions.tags)) { - formData.append('tags', uploadOptions.tags.join(",")); - } else if (key === "responseFields" && Array.isArray(uploadOptions.responseFields)) { - formData.append('responseFields', uploadOptions.responseFields.join(",")); - } else if (key === "extensions" && Array.isArray(uploadOptions.extensions)) { - formData.append('extensions', JSON.stringify(uploadOptions.extensions)); - } else if (key === "customMetadata" && typeof uploadOptions.customMetadata === "object" && - !Array.isArray(uploadOptions.customMetadata) && uploadOptions.customMetadata !== null) { - formData.append('customMetadata', JSON.stringify(uploadOptions.customMetadata)); - } else if(uploadOptions[key] !== undefined) { - formData.append(key, String(uploadOptions[key])); - } - } - } - - formData.append("publicKey", options.publicKey); - - request(xhr, formData, { ...options, authenticationEndpoint: options.authenticationEndpoint }, callback); -}; diff --git a/src/url.ts b/src/url.ts new file mode 100644 index 0000000..3a74faa --- /dev/null +++ b/src/url.ts @@ -0,0 +1,314 @@ +import type { SrcOptions, ImageOverlay, SolidColorOverlay, SubtitleOverlay, TextOverlay, Transformation, VideoOverlay } from "./interfaces"; +import transformationUtils, { safeBtoa } from "./utils/transformation"; +const TRANSFORMATION_PARAMETER = "tr"; +const SIMPLE_OVERLAY_PATH_REGEX = new RegExp('^[a-zA-Z0-9-._/ ]*$') +const SIMPLE_OVERLAY_TEXT_REGEX = new RegExp('^[a-zA-Z0-9-._ ]*$') // These characters are selected by testing actual URLs on both path and query parameters. If and when backend starts supporting wide range of characters, this regex should be updated to improve URL readability. + +function removeTrailingSlash(str: string) { + if (typeof str == "string" && str[str.length - 1] == "/") { + str = str.substring(0, str.length - 1); + } + return str; +} + +function removeLeadingSlash(str: string) { + if (typeof str == "string" && str[0] == "/") { + str = str.slice(1); + } + return str; +} + +function pathJoin(parts: string[], sep?: string) { + var separator = sep || "/"; + var replace = new RegExp(separator + "{1,}", "g"); + return parts.join(separator).replace(replace, separator); +} + +/** + * Builds a source URL with the given options. + * + * @param {SrcOptions} opts - The options for building the source URL. + * @returns {string} The constructed source URL. + */ +export const buildSrc = (opts: SrcOptions): string => { + opts.urlEndpoint = opts.urlEndpoint || ""; + opts.src = opts.src || ""; + opts.transformationPosition = opts.transformationPosition || "query"; + + if (!opts.src) { + return ""; + } + + const isAbsoluteURL = opts.src.startsWith("http://") || opts.src.startsWith("https://"); + + var urlObj, isSrcParameterUsedForURL, urlEndpointPattern; + + try { + if (!isAbsoluteURL) { + urlEndpointPattern = new URL(opts.urlEndpoint).pathname; + urlObj = new URL(pathJoin([opts.urlEndpoint.replace(urlEndpointPattern, ""), opts.src])); + } else { + urlObj = new URL(opts.src!); + isSrcParameterUsedForURL = true; + } + } catch (e) { + console.error(e) + return ""; + } + + for (var i in opts.queryParameters) { + urlObj.searchParams.append(i, String(opts.queryParameters[i])); + } + + var transformationString = buildTransformationString(opts.transformation); + + if (transformationString && transformationString.length) { + if (!transformationUtils.addAsQueryParameter(opts) && !isSrcParameterUsedForURL) { + urlObj.pathname = pathJoin([ + TRANSFORMATION_PARAMETER + transformationUtils.getChainTransformDelimiter() + transformationString, + urlObj.pathname, + ]); + } + } + + if (urlEndpointPattern) { + urlObj.pathname = pathJoin([urlEndpointPattern, urlObj.pathname]); + } else { + urlObj.pathname = pathJoin([urlObj.pathname]); + } + + if (transformationString && transformationString.length) { + if (transformationUtils.addAsQueryParameter(opts) || isSrcParameterUsedForURL) { + if (urlObj.searchParams.toString() !== "") { // In 12 node.js .size was not there. So, we need to check if it is an object or not. + return `${urlObj.href}&${TRANSFORMATION_PARAMETER}=${transformationString}`; + } + else { + return `${urlObj.href}?${TRANSFORMATION_PARAMETER}=${transformationString}`; + } + } + } + + return urlObj.href; +}; + +function processInputPath(str: string, enccoding: string): string { + // Remove leading and trailing slashes + str = removeTrailingSlash(removeLeadingSlash(str)); + if (enccoding === "plain") { + return `i-${str.replace(/\//g, "@@")}`; + } + if (enccoding === "base64") { + return `ie-${encodeURIComponent(safeBtoa(str))}`; + } + if (SIMPLE_OVERLAY_PATH_REGEX.test(str)) { + return `i-${str.replace(/\//g, "@@")}`; + } else { + return `ie-${encodeURIComponent(safeBtoa(str))}`; + } +} + +function processText(str: string, enccoding: TextOverlay["encoding"]): string { + if (enccoding === "plain") { + return `i-${encodeURIComponent(str)}`; + } + if (enccoding === "base64") { + return `ie-${encodeURIComponent(safeBtoa(str))}`; + } + if (SIMPLE_OVERLAY_TEXT_REGEX.test(str)) { + return `i-${encodeURIComponent(str)}`; + } + return `ie-${encodeURIComponent(safeBtoa(str))}`; +} + +function processOverlay(overlay: Transformation["overlay"]): string | undefined { + const entries = []; + + const { type, layerMode, position = {}, timing = {}, transformation = [] } = overlay || {}; + + if (!type) { + return; + } + + switch (type) { + case "text": { + const textOverlay = overlay as TextOverlay; + if (!textOverlay.text) { + return; + } + const enccoding = textOverlay.encoding || "auto"; + + entries.push("l-text"); + entries.push(processText(textOverlay.text, enccoding)); + } + break; + case "image": + entries.push("l-image"); + { + const imageOverlay = overlay as ImageOverlay; + const enccoding = imageOverlay.encoding || "auto"; + if (imageOverlay.input) { + entries.push(processInputPath(imageOverlay.input, enccoding)); + } else { + return; + } + } + break; + case "video": + entries.push("l-video"); + { + const videoOverlay = overlay as VideoOverlay; + const enccoding = videoOverlay.encoding || "auto"; + if (videoOverlay.input) { + entries.push(processInputPath(videoOverlay.input, enccoding)); + } else { + return; + } + } + break; + case "subtitle": + entries.push("l-subtitles"); + { + const subtitleOverlay = overlay as SubtitleOverlay; + const enccoding = subtitleOverlay.encoding || "auto"; + if (subtitleOverlay.input) { + entries.push(processInputPath(subtitleOverlay.input, enccoding)); + } else { + return; + } + } + break; + case "solidColor": + entries.push("l-image"); + entries.push(`i-ik_canvas`); + { + const solidColorOverlay = overlay as SolidColorOverlay; + if (solidColorOverlay.color) { + entries.push(`bg-${solidColorOverlay.color}`); + } else { + return; + } + } + break; + } + + // Add layer mode if specified + if (layerMode) { + entries.push(`lm-${layerMode}`); + } + + const { x, y, xCenter, yCenter, anchorPoint, focus } = position; + if (x) { + entries.push(`lx-${x}`); + } + if (y) { + entries.push(`ly-${y}`); + } + if (xCenter) { + entries.push(`lxc-${xCenter}`); + } + if (yCenter) { + entries.push(`lyc-${yCenter}`); + } + if (anchorPoint) { + entries.push(`lap-${anchorPoint}`); + } + if (focus) { + entries.push(`lfo-${focus}`); + } + + const { start, end, duration } = timing; + + if (start) { + entries.push(`lso-${start}`); + } + if (end) { + entries.push(`leo-${end}`); + } + if (duration) { + entries.push(`ldu-${duration}`); + } + + const transformationString = buildTransformationString(transformation); + + if (transformationString && transformationString.trim() !== "") entries.push(transformationString); + + entries.push("l-end"); + + return entries.join(transformationUtils.getTransformDelimiter()); +} + +/** + * Builds a transformation string from the given transformations. + * + * @param {Transformation[] | undefined} transformation - The transformations to apply. + * @returns {string} The constructed transformation string. + */ +export const buildTransformationString = function (transformation: Transformation[] | undefined): string { + if (!Array.isArray(transformation)) { + return ""; + } + + var parsedTransforms: string[] = []; + for (var i = 0, l = transformation.length; i < l; i++) { + var parsedTransformStep: string[] = []; + for (var key in transformation[i]) { + let value = transformation[i][key as keyof Transformation]; + if (value === undefined || value === null) { + continue; + } + + if (key === "overlay" && typeof value === "object") { + var rawString = processOverlay(value as Transformation["overlay"]); + if (rawString && rawString.trim() !== "") { + parsedTransformStep.push(rawString); + } + continue; // Always continue as overlay is processed. + } + + var transformKey = transformationUtils.getTransformKey(key); + if (!transformKey) { + transformKey = key; + } + + if (transformKey === "") { + continue; + } + + if ( + ["e-grayscale", "e-contrast", "e-removedotbg", "e-bgremove", "e-upscale", "e-retouch", "e-genvar"].includes(transformKey) + ) { + if (value === true || value === "-" || value === "true") { + parsedTransformStep.push(transformKey); + } else { + // Any other value means that the effect should not be applied + continue; + } + } else if ( + ["e-sharpen", "e-shadow", "e-gradient", "e-usm", "e-dropshadow"].includes(transformKey) && + (value.toString().trim() === "" || value === true || value === "true") + ) { + parsedTransformStep.push(transformKey); + } else if (key === "raw") { + parsedTransformStep.push(transformation[i][key] as string); + } else { + if (transformKey === "di" || transformKey === "ff") { + value = removeTrailingSlash(removeLeadingSlash(value as string || "")); + value = value.replace(/\//g, "@@"); + } + if (transformKey === "sr" && Array.isArray(value)) { + value = value.join("_"); + } + // Special case for trim with empty string - should be treated as true + if (transformKey === "t" && value.toString().trim() === "") { + value = "true"; + } + parsedTransformStep.push([transformKey, value].join(transformationUtils.getTransformKeyValueDelimiter())); + } + } + if (parsedTransformStep.length) { + parsedTransforms.push(parsedTransformStep.join(transformationUtils.getTransformDelimiter())); + } + } + + return parsedTransforms.join(transformationUtils.getChainTransformDelimiter()); +} diff --git a/src/url/builder.ts b/src/url/builder.ts deleted file mode 100644 index fedeae1..0000000 --- a/src/url/builder.ts +++ /dev/null @@ -1,107 +0,0 @@ -import { ImageKitOptions, UrlOptions } from "../interfaces"; -import { Transformation } from "../interfaces/Transformation"; -import transformationUtils from "../utils/transformation"; -const TRANSFORMATION_PARAMETER = "tr"; - -function removeTrailingSlash(str: string) { - if (typeof str == "string" && str[str.length - 1] == "/") { - str = str.substring(0, str.length - 1); - } - return str; -} - -function removeLeadingSlash(str: string) { - if (typeof str == "string" && str[0] == "/") { - str = str.slice(1); - } - return str; -} - -function pathJoin(parts: string[], sep?: string) { - var separator = sep || "/"; - var replace = new RegExp(separator + "{1,}", "g"); - return parts.join(separator).replace(replace, separator); -} - -export const buildURL = (opts: UrlOptions & ImageKitOptions) => { - if (!opts.path && !opts.src) { - return ""; - } - - var urlObj, isSrcParameterUsedForURL, urlEndpointPattern; - - try { - if (opts.path) { - urlEndpointPattern = new URL(opts.urlEndpoint).pathname; - urlObj = new URL(pathJoin([opts.urlEndpoint.replace(urlEndpointPattern, ""), opts.path])); - } else { - urlObj = new URL(opts.src!); - isSrcParameterUsedForURL = true; - } - } catch (e) { - console.error(e) - return ""; - } - - // if (opts.sdkVersion && opts.sdkVersion.trim() != "") { - // urlObj.searchParams.append("ik-sdk-version", opts.sdkVersion.trim()); - // } - - for (var i in opts.queryParameters) { - urlObj.searchParams.append(i, String(opts.queryParameters[i])); - } - - var transformationString = constructTransformationString(opts.transformation); - - if (transformationString && transformationString.length) { - if (transformationUtils.addAsQueryParameter(opts) || isSrcParameterUsedForURL) { - urlObj.searchParams.append(TRANSFORMATION_PARAMETER, transformationString); - } else { - urlObj.pathname = pathJoin([ - TRANSFORMATION_PARAMETER + transformationUtils.getChainTransformDelimiter() + transformationString, - urlObj.pathname, - ]); - } - } - - if (urlEndpointPattern) { - urlObj.pathname = pathJoin([urlEndpointPattern, urlObj.pathname]); - } else { - urlObj.pathname = pathJoin([urlObj.pathname]); - } - - return urlObj.href; -}; - -function constructTransformationString(transformation: Transformation[] | undefined) { - if (!Array.isArray(transformation)) { - return ""; - } - - var parsedTransforms = []; - for (var i = 0, l = transformation.length; i < l; i++) { - var parsedTransformStep = []; - for (var key in transformation[i]) { - var transformKey = transformationUtils.getTransformKey(key); - if (!transformKey) { - transformKey = key; - } - - if (transformation[i][key] === "-") { - parsedTransformStep.push(transformKey); - } else if (key === "raw") { - parsedTransformStep.push(transformation[i][key]); - } else { - var value = transformation[i][key]; - if (transformKey === "oi" || transformKey === "di") { - value = removeTrailingSlash(removeLeadingSlash(value || "")); - value = value.replace(/\//g, "@@"); - } - parsedTransformStep.push([transformKey, value].join(transformationUtils.getTransformKeyValueDelimiter())); - } - } - parsedTransforms.push(parsedTransformStep.join(transformationUtils.getTransformDelimiter())); - } - - return parsedTransforms.join(transformationUtils.getChainTransformDelimiter()); -} diff --git a/src/url/index.ts b/src/url/index.ts deleted file mode 100644 index 8503b76..0000000 --- a/src/url/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/* - URL builder -*/ -import { ImageKitOptions, UrlOptions } from "../interfaces"; -import { buildURL } from "./builder"; - -export const url = (urlOpts: UrlOptions, defaultOptions: ImageKitOptions) => { - return buildURL({ - ...defaultOptions, - ...urlOpts, - }); -}; diff --git a/src/utils/request.ts b/src/utils/request.ts deleted file mode 100644 index dc351f2..0000000 --- a/src/utils/request.ts +++ /dev/null @@ -1,131 +0,0 @@ -import respond from "../utils/respond"; -import errorMessages from "../constants/errorMessages" -import { ImageKitOptions, UploadResponse } from "../interfaces"; -import IKResponse from "../interfaces/IKResponse"; - -interface SignatureResponse { - signature: string - expire: number - token: string -} - -function getResponseHeaderMap(xhr: XMLHttpRequest) { - const headers: Record = {}; - const responseHeaders = xhr.getAllResponseHeaders(); - if (Object.keys(responseHeaders).length) { - responseHeaders - .trim() - .split(/[\r\n]+/) - .map(value => value.split(/: /)) - .forEach(keyValue => { - headers[keyValue[0].trim()] = keyValue[1].trim(); - }); - } - return headers; -} - -const addResponseHeadersAndBody = (body: any, xhr: XMLHttpRequest): IKResponse => { - let response = { ...body }; - const responseMetadata = { - statusCode: xhr.status, - headers: getResponseHeaderMap(xhr) - } - Object.defineProperty(response, "$ResponseMetadata", { - value: responseMetadata, - enumerable: false, - writable: false - }); - return response as IKResponse; -} - -export const request = ( - uploadFileXHR: XMLHttpRequest, - formData: FormData, - options: ImageKitOptions & { authenticationEndpoint: string }, - callback?: (err: Error | null, response: UploadResponse | null) => void) => { - - generateSignatureToken(options.authenticationEndpoint).then((signaturObj) => { - formData.append("signature", signaturObj.signature); - formData.append("expire", String(signaturObj.expire)); - formData.append("token", signaturObj.token); - - uploadFile(uploadFileXHR, formData).then((result) => { - return respond(false, result, callback); - }, (ex) => { - return respond(true, ex, callback); - }); - }, (ex) => { - return respond(true, ex, callback); - }); -} - -export const generateSignatureToken = ( - authenticationEndpoint: string -): Promise => { - return new Promise((resolve, reject) => { - var xhr = new XMLHttpRequest(); - xhr.timeout = 60000; - var urlObj = new URL(authenticationEndpoint); - urlObj.searchParams.set("t", Math.random().toString()); - xhr.open('GET', urlObj.toString()); - xhr.ontimeout = function (e) { - return reject(errorMessages.AUTH_ENDPOINT_TIMEOUT); - }; - xhr.onerror = function () { - return reject(errorMessages.AUTH_ENDPOINT_NETWORK_ERROR); - } - xhr.onload = function () { - if (xhr.status === 200) { - try { - var body = JSON.parse(xhr.responseText); - var obj = { - signature: body.signature, - expire: body.expire, - token: body.token - } - if (!obj.signature || !obj.expire || !obj.token) { - return reject(errorMessages.AUTH_INVALID_RESPONSE); - } - return resolve(obj); - } catch (ex) { - return reject(errorMessages.AUTH_INVALID_RESPONSE); - } - } else { - return reject(errorMessages.AUTH_INVALID_RESPONSE); - } - }; - xhr.send(); - }); -} - -export const uploadFile = ( - uploadFileXHR: XMLHttpRequest, - formData: FormData -): Promise | Error> => { - return new Promise((resolve, reject) => { - uploadFileXHR.open('POST', 'https://upload.imagekit.io/api/v1/files/upload'); - uploadFileXHR.onerror = function (e) { - return reject(errorMessages.UPLOAD_ENDPOINT_NETWORK_ERROR); - } - uploadFileXHR.onload = function () { - if (uploadFileXHR.status === 200) { - try { - var body = JSON.parse(uploadFileXHR.responseText); - var uploadResponse = addResponseHeadersAndBody(body, uploadFileXHR); - return resolve(uploadResponse); - } catch (ex: any) { - return reject(ex); - } - } else { - try { - var body = JSON.parse(uploadFileXHR.responseText); - var uploadError = addResponseHeadersAndBody(body, uploadFileXHR); - return reject(uploadError) - } catch (ex: any) { - return reject(ex); - } - } - }; - uploadFileXHR.send(formData); - }); -} \ No newline at end of file diff --git a/src/utils/respond.ts b/src/utils/respond.ts deleted file mode 100644 index 06d02f6..0000000 --- a/src/utils/respond.ts +++ /dev/null @@ -1,9 +0,0 @@ -export default function(isError: boolean, response: any, callback?: (err: Error | null, response: any) => void) { - if(typeof callback == "function") { - if(isError) { - callback(response, null); - } else { - callback(null, response); - } - } -}; \ No newline at end of file diff --git a/src/utils/transformation.ts b/src/utils/transformation.ts index ef4ec26..7a6c7c4 100644 --- a/src/utils/transformation.ts +++ b/src/utils/transformation.ts @@ -1,24 +1,16 @@ import supportedTransforms from "../constants/supportedTransforms"; -import { ImageKitOptions, TransformationPosition } from "../interfaces"; +import { TransformationPosition, SrcOptions } from "../interfaces"; -const DEFAULT_TRANSFORMATION_POSITION : TransformationPosition = "path"; -const QUERY_TRANSFORMATION_POSITION : TransformationPosition = "query"; -const VALID_TRANSFORMATION_POSITIONS = [DEFAULT_TRANSFORMATION_POSITION, QUERY_TRANSFORMATION_POSITION]; -const CHAIN_TRANSFORM_DELIMITER : string = ":"; -const TRANSFORM_DELIMITER : string = ","; -const TRANSFORM_KEY_VALUE_DELIMITER : string = "-"; +const QUERY_TRANSFORMATION_POSITION: TransformationPosition = "query"; +const PATH_TRANSFORMATION_POSITION: TransformationPosition = "path"; +const CHAIN_TRANSFORM_DELIMITER: string = ":"; +const TRANSFORM_DELIMITER: string = ","; +const TRANSFORM_KEY_VALUE_DELIMITER: string = "-"; export default { - getDefault: (): TransformationPosition => { - return DEFAULT_TRANSFORMATION_POSITION; - }, - addAsQueryParameter: (options: ImageKitOptions) => { + addAsQueryParameter: (options: SrcOptions) => { return options.transformationPosition === QUERY_TRANSFORMATION_POSITION; }, - validParameters: (options: ImageKitOptions) => { - if(typeof options.transformationPosition == "undefined") return false; - return VALID_TRANSFORMATION_POSITIONS.indexOf(options.transformationPosition) != -1; - }, getTransformKey: function (transform: string) { if (!transform) { return ""; } @@ -33,4 +25,17 @@ export default { getTransformKeyValueDelimiter: function () { return TRANSFORM_KEY_VALUE_DELIMITER; } -} \ No newline at end of file +} + +export const safeBtoa = function (str: string): string { + // Prefer Buffer when available (Node.js / SSR): handles UTF-8 natively. + if (typeof (globalThis as any).Buffer !== "undefined") { + return (globalThis as any).Buffer.from(str, "utf8").toString("base64"); + } + + // Browser: btoa() throws on characters with code points > 0xFF, so convert + // the string to UTF-8 bytes first, then base64-encode them (per MDN). + const bytes = new TextEncoder().encode(str); + const binary = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join(""); + return btoa(binary); +}; \ No newline at end of file diff --git a/test-app/.gitignore b/test-app/.gitignore new file mode 100644 index 0000000..48abb2a --- /dev/null +++ b/test-app/.gitignore @@ -0,0 +1,4 @@ +node_modules/ +test-results/ +playwright-report/ +.playwright/ diff --git a/test-app/index.html b/test-app/index.html new file mode 100644 index 0000000..a2b4cd0 --- /dev/null +++ b/test-app/index.html @@ -0,0 +1,80 @@ + + + + + + ImageKit JavaScript SDK - URL Generation Test App + + +
+

ImageKit JavaScript SDK

+

URL generation playground. The SDK is loaded as the built ESM bundle and runs entirely in the browser.

+ +
+

+ +
+

+ +
+

+ + + +

Generated URL

+ + +
+ preview +
+
+ + + + diff --git a/test-app/package-lock.json b/test-app/package-lock.json new file mode 100644 index 0000000..e65c62d --- /dev/null +++ b/test-app/package-lock.json @@ -0,0 +1,78 @@ +{ + "name": "imagekit-javascript-test-app", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "imagekit-javascript-test-app", + "version": "1.0.0", + "devDependencies": { + "@playwright/test": "^1.48.0" + } + }, + "node_modules/@playwright/test": { + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.60.0.tgz", + "integrity": "sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.60.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/playwright": { + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.60.0.tgz", + "integrity": "sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.60.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, + "node_modules/playwright-core": { + "version": "1.60.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.60.0.tgz", + "integrity": "sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "playwright-core": "cli.js" + }, + "engines": { + "node": ">=18" + } + } + } +} diff --git a/test-app/package.json b/test-app/package.json new file mode 100644 index 0000000..6bb2377 --- /dev/null +++ b/test-app/package.json @@ -0,0 +1,14 @@ +{ + "name": "imagekit-javascript-test-app", + "version": "1.0.0", + "private": true, + "type": "module", + "description": "Browser test app for the ImageKit JavaScript SDK. Loads the built SDK bundle in a real browser so Playwright can cover URL-generation edge cases (e.g. Unicode base64) that the Node-based unit tests cannot.", + "scripts": { + "serve": "node server.mjs", + "test": "playwright test" + }, + "devDependencies": { + "@playwright/test": "^1.48.0" + } +} diff --git a/test-app/playwright.config.ts b/test-app/playwright.config.ts new file mode 100644 index 0000000..b2ee711 --- /dev/null +++ b/test-app/playwright.config.ts @@ -0,0 +1,24 @@ +import { defineConfig, devices } from "@playwright/test"; + +export default defineConfig({ + testDir: "./tests", + fullyParallel: true, + forbidOnly: !!process.env.CI, + retries: process.env.CI ? 2 : 0, + reporter: "list", + use: { + baseURL: "http://localhost:4321", + trace: "on-first-retry", + }, + projects: [ + { + name: "chromium", + use: { ...devices["Desktop Chrome"] }, + }, + ], + webServer: { + command: "npm run serve", + url: "http://localhost:4321", + reuseExistingServer: !process.env.CI, + }, +}); diff --git a/test-app/server.mjs b/test-app/server.mjs new file mode 100644 index 0000000..035fee4 --- /dev/null +++ b/test-app/server.mjs @@ -0,0 +1,45 @@ +// Minimal zero-dependency static file server. +// Serves the repository root so the test app at /test-app/index.html can import +// the built SDK bundle from /dist/imagekit.esm.js. Used by Playwright's webServer. +import { createServer } from "node:http"; +import { readFile } from "node:fs/promises"; +import { fileURLToPath } from "node:url"; +import { dirname, join, normalize, extname } from "node:path"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); +const ROOT = join(__dirname, ".."); +const PORT = Number(process.env.PORT) || 4321; + +const MIME = { + ".html": "text/html; charset=utf-8", + ".js": "text/javascript; charset=utf-8", + ".mjs": "text/javascript; charset=utf-8", + ".css": "text/css; charset=utf-8", + ".json": "application/json; charset=utf-8", + ".map": "application/json; charset=utf-8", + ".svg": "image/svg+xml", +}; + +const server = createServer(async (req, res) => { + try { + let pathname = decodeURIComponent(new URL(req.url, `http://localhost`).pathname); + if (pathname === "/") pathname = "/test-app/index.html"; + + // Resolve and prevent path traversal outside ROOT. + const filePath = normalize(join(ROOT, pathname)); + if (!filePath.startsWith(ROOT)) { + res.writeHead(403).end("Forbidden"); + return; + } + + const data = await readFile(filePath); + res.writeHead(200, { "content-type": MIME[extname(filePath)] || "application/octet-stream" }); + res.end(data); + } catch { + res.writeHead(404).end("Not found"); + } +}); + +server.listen(PORT, () => { + console.log(`Static server running at http://localhost:${PORT}`); +}); diff --git a/test-app/tests/basic.spec.ts b/test-app/tests/basic.spec.ts new file mode 100644 index 0000000..661acea --- /dev/null +++ b/test-app/tests/basic.spec.ts @@ -0,0 +1,1303 @@ +import { test, expect } from "./fixtures"; + +async function buildSrc(page: import("@playwright/test").Page, opts: any): Promise { + return page.evaluate((o) => (window as any).buildSrc(o), opts); +} + +test.describe("URL generation", () => { + test('should return an empty string when src is not provided', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query" + }); + + expect(url).toBe(""); + }); + + test('should return an empty string when src is /', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/" + }); + + expect(url).toBe("https://ik.imagekit.io/test_url_endpoint/"); + }); + + test('should return an empty string when src is invalid', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "https://" + }); + + expect(url).toBe(""); + }); + + test('should generate a valid URL when src is provided without transformation', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path.jpg" + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path.jpg`); + }); + + test('should encode a src path containing Hindi (non-ASCII) characters', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/demo", + src: "/sdk-testing-files/हिन्दी.png" + }); + + expect(url).toBe(`https://ik.imagekit.io/demo/sdk-testing-files/%E0%A4%B9%E0%A4%BF%E0%A4%A8%E0%A5%8D%E0%A4%A6%E0%A5%80.png`); + }); + + test('should generate a valid URL when a src is provided without transformation', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg" + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg`); + }); + + test('should generate a valid URL when undefined transformation parameters are provided with path', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/test_path_alt.jpg", + transformation: undefined, + transformationPosition: "query" + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg`); + }); + + test("By default transformationPosition should be query", async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/test_path.jpg", + transformation: [ + { + height: "300", + width: "400" + }, + { + rotation: 90 + } + ] + }); + expect(url).toBe("https://ik.imagekit.io/test_url_endpoint/test_path.jpg?tr=h-300,w-400:rt-90"); + }); + + test('should generate the URL without sdk version', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/test_path.jpg", + transformation: [ + { + height: "300", + width: "400" + } + ], + transformationPosition: "path" + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/tr:h-300,w-400/test_path.jpg`); + }); + + test('should generate the correct URL with a valid src and transformation', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path.jpg", + transformation: [ + { + height: "300", + width: "400" + } + ] + }); + + // Now transformed URL goes into query since transformationPosition is "query". + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path.jpg?tr=h-300,w-400`); + }); + + test('should generate the correct URL when the provided path contains multiple leading slashes', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "///test_path.jpg", + transformation: [ + { + height: "300", + width: "400" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path.jpg?tr=h-300,w-400`); + }); + + test('should generate the correct URL when the urlEndpoint is overridden', async ({ page }) => { + const url = await buildSrc(page, { + // We do not override urlEndpoint here + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint_alt", + transformationPosition: "query", + src: "/test_path.jpg", + transformation: [ + { + height: "300", + width: "400" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint_alt/test_path.jpg?tr=h-300,w-400`); + }); + + test('should generate the correct URL with transformationPosition as query parameter when src is provided', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/test_path.jpg", + transformationPosition: "query", + transformation: [ + { + height: "300", + width: "400" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path.jpg?tr=h-300,w-400`); + }); + + test('should generate the correct URL with a valid src parameter and transformation', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg", + transformation: [ + { + height: "300", + width: "400" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg?tr=h-300,w-400`); + }); + + test('should generate the correct URL with transformationPosition as query parameter when absolute src is provided', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg", + transformationPosition: "query", + transformation: [ + { + height: "300", + width: "400" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg?tr=h-300,w-400`); + }); + + test('should merge query parameters correctly in the generated URL', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg?t1=v1", + queryParameters: { t2: "v2", t3: "v3" }, + transformation: [ + { + height: "300", + width: "400" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg?t1=v1&t2=v2&t3=v3&tr=h-300,w-400`); + }); + + test('should generate the correct URL with chained transformations', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path.jpg", + transformation: [ + { + height: "300", + width: "400" + }, + { + rt: "90" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path.jpg?tr=h-300,w-400:rt-90`); + }); + + test('should generate the correct URL with chained transformations including a new undocumented transformation parameter', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path.jpg", + transformation: [ + { + height: "300", + width: "400" + }, + { + rndm_trnsf: "abcd" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path.jpg?tr=h-300,w-400:rndm_trnsf-abcd`); + }); + + test('should generate the correct URL when overlay image transformation is provided', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path.jpg", + transformation: [ + { + height: "300", + width: "400", + raw: "l-image,i-overlay.jpg,w-100,b-10_CDDC39,l-end" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path.jpg?tr=h-300,w-400,l-image,i-overlay.jpg,w-100,b-10_CDDC39,l-end`); + }); + + test('should generate the correct URL when overlay image transformation contains a slash in the overlay path', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path.jpg", + transformation: [ + { + height: "300", + width: "400", + raw: "l-image,i-/path/to/overlay.jpg,w-100,b-10_CDDC39,l-end" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path.jpg?tr=h-300,w-400,l-image,i-/path/to/overlay.jpg,w-100,b-10_CDDC39,l-end`); + }); + + test('should generate the correct URL when border transformation is applied', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path.jpg", + transformation: [ + { + height: "300", + width: "400", + border: "20_FF0000" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path.jpg?tr=h-300,w-400,b-20_FF0000`); + }); + + test('should generate the correct URL when transformation has empty key and value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path.jpg", + transformation: [ + { + "": "" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path.jpg`); + }); + + test('should generate the correct URL when an undefined transform is provided', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path.jpg", + transformation: [ + { + "undefined-transform": "true" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path.jpg?tr=undefined-transform-true`); + }); + + test('should generate the correct URL when transformation key has an empty value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path.jpg", + transformation: [ + { + defaultImage: "" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path.jpg?tr=di-`); + }); + + test('should generate the correct URL when transformation key has \'-\' as its value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path.jpg", + transformation: [ + { + contrastStretch: "-" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path.jpg?tr=e-contrast`); + }); + + test('should skip transformation parameters that are undefined or null', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + defaultImage: "/test_path.jpg", + quality: undefined, + contrastStretch: null + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=di-test_path.jpg`); + }); + + test('should skip transformation parameters that are false', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + defaultImage: "/test_path.jpg", + contrastStretch: false + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=di-test_path.jpg`); + }); + + test('should include only the key when transformation value is an empty string', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + defaultImage: "/test_path.jpg", + shadow: "" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=di-test_path.jpg,e-shadow`); + }); + + test('should include both key and value when transformation parameter value is provided', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + defaultImage: "/test_path.jpg", + shadow: "bl-15_st-40_x-10_y-N5" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=di-test_path.jpg,e-shadow-bl-15_st-40_x-10_y-N5`); + }); + + test('should generate the correct URL when trim transformation is set to true as a boolean', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + defaultImage: "/test_path.jpg", + trim: true + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=di-test_path.jpg,t-true`); + }); + + test('should generate the correct URL when trim transformation is set to true as a string', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + defaultImage: "/test_path.jpg", + trim: "true" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=di-test_path.jpg,t-true`); + }); + + test('should generate the correct URL for AI background removal when set to true', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + aiRemoveBackground: true + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-bgremove`); + }); + + test('should generate the correct URL for AI background removal when \'true\' is provided as a string', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + aiRemoveBackground: "true" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-bgremove`); + }); + + test('should not apply AI background removal when value is not true', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + aiRemoveBackground: "false" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg`); + }); + + test('should generate the correct URL for external AI background removal when set to true', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + aiRemoveBackgroundExternal: true + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-removedotbg`); + }); + + test('should generate the correct URL for external AI background removal when \'true\' is provided as a string', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + aiRemoveBackgroundExternal: "true" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-removedotbg`); + }); + + test('should not apply external AI background removal when value is not true', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + aiRemoveBackgroundExternal: "false" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg`); + }); + + test('should generate the correct URL when gradient transformation is provided as a string', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + gradient: "ld-top_from-green_to-00FF0010_sp-1" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-gradient-ld-top_from-green_to-00FF0010_sp-1`); + }); + + test('should generate the correct URL when gradient transformation is provided as an empty string', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + gradient: "" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-gradient`); + }); + + test('should generate the correct URL when gradient transformation is set to true', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + gradient: true + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-gradient`); + }); + + test('should generate the correct URL when AI drop shadow transformation is set to true', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + aiDropShadow: true + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-dropshadow`); + }); + + test('should generate the correct URL when AI drop shadow transformation is provided as an empty string', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + aiDropShadow: "" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-dropshadow`); + }); + + test('should generate the correct URL when AI drop shadow transformation is provided with a specific string value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + aiDropShadow: "az-45" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-dropshadow-az-45`); + }); + + test('should generate the correct URL when shadow transformation is set to true', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + shadow: true + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-shadow`); + }); + + test('should generate the correct URL when shadow transformation is provided as an empty string', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + shadow: "" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-shadow`); + }); + + test('should generate the correct URL when shadow transformation is provided with a specific string value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + shadow: "bl-15_st-40_x-10_y-N5" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-shadow-bl-15_st-40_x-10_y-N5`); + }); + + test('should generate the correct URL when sharpen transformation is set to true', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + sharpen: true + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-sharpen`); + }); + + test('should generate the correct URL when sharpen transformation is provided as an empty string', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + sharpen: "" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-sharpen`); + }); + + test('should generate the correct URL when sharpen transformation is provided with a number value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + sharpen: 10 + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-sharpen-10`); + }); + + test('should generate the correct URL when unsharpMask transformation is set to true', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + unsharpMask: true + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-usm`); + }); + + test('should generate the correct URL when unsharpMask transformation is provided as an empty string', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + unsharpMask: "" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-usm`); + }); + + test('should generate the correct URL when unsharpMask transformation is provided with a string value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + unsharpMask: "2-2-0.8-0.024" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=e-usm-2-2-0.8-0.024`); + }); + + test('should generate the correct URL for trim transformation when set to true (boolean)', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + trim: true + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=t-true`); + }); + + test('should generate the correct URL for trim transformation when provided as an empty string', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + trim: "" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=t-true`); + }); + + test('should generate the correct URL for trim transformation when provided with a number value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + trim: 5 + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=t-5`); + }); + + // Width parameter tests + test('should generate the correct URL for width transformation when provided with a number value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + width: 400 + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=w-400`); + }); + + test('should generate the correct URL for width transformation when provided with a string value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + width: "400" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=w-400`); + }); + + test('should generate the correct URL for width transformation when provided with an arithmetic expression', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + width: "iw_div_2" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=w-iw_div_2`); + }); + + // Height parameter tests + test('should generate the correct URL for height transformation when provided with a number value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + height: 300 + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=h-300`); + }); + + test('should generate the correct URL for height transformation when provided with a string value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + height: "300" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=h-300`); + }); + + test('should generate the correct URL for height transformation when provided with an arithmetic expression', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + height: "ih_mul_0.5" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=h-ih_mul_0.5`); + }); + + // AspectRatio parameter tests + test('should generate the correct URL for aspectRatio transformation when provided with a string value in colon format', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + aspectRatio: "4:3" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=ar-4:3`); + }); + + test('should generate the correct URL for aspectRatio transformation when provided with an alternate underscore format', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + aspectRatio: "4_3" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=ar-4_3`); + }); + + test('should generate the correct URL for aspectRatio transformation when provided with an arithmetic expression', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + aspectRatio: "iar_div_2" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=ar-iar_div_2`); + }); + + // Background parameter tests + test('should generate the correct URL for background transformation when provided with a solid color', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + background: "FF0000" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=bg-FF0000`); + }); + + test('should generate the correct URL for background transformation when provided with the blurred option', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + background: "blurred" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=bg-blurred`); + }); + + test('should generate the correct URL for background transformation when provided with the genfill option', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + background: "genfill" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=bg-genfill`); + }); + + // Crop parameter tests + test('should generate the correct URL for crop transformation when provided with force value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + crop: "force" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=c-force`); + }); + + test('should generate the correct URL for crop transformation when provided with at_max value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + crop: "at_max" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=c-at_max`); + }); + + // CropMode parameter tests + test('should generate the correct URL for cropMode transformation when provided with pad_resize', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + cropMode: "pad_resize" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=cm-pad_resize`); + }); + + test('should generate the correct URL for cropMode transformation when provided with extract value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + cropMode: "extract" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=cm-extract`); + }); + + // Focus parameter tests + test('should generate the correct URL for focus transformation when provided with a string value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + focus: "center" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=fo-center`); + }); + + test('should generate the correct URL for focus transformation when face detection is specified', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + focus: "face" + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=fo-face`); + }); + + // Quality parameter test + test('should generate the correct URL for quality transformation when provided with a number value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + quality: 80 + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=q-80`); + }); + + // Coordinate parameters tests + test('should generate the correct URL for x coordinate transformation when provided with a number value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + x: 10 + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=x-10`); + }); + + test('should generate the correct URL for y coordinate transformation when provided with a number value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + y: 20 + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=y-20`); + }); + + test('should generate the correct URL for xCenter transformation when provided with a number value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + xCenter: 30 + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=xc-30`); + }); + + test('should generate the correct URL for yCenter transformation when provided with a number value', async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path1.jpg", + transformation: [ + { + yCenter: 40 + } + ] + }); + + expect(url).toBe(`https://ik.imagekit.io/test_url_endpoint/test_path1.jpg?tr=yc-40`); + }); + + test('Including deprecated properties', async ({ page }) => { + // This is just testing how the SDK constructs the URL, not actual valid transformations. + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path.jpg", + transformation: [ + { + height: 300, + width: 400, + aspectRatio: '4-3', + quality: 40, + crop: 'force', + cropMode: 'extract', + focus: 'left', + format: 'jpeg', + radius: 50, + bg: "A94D34", + border: "5-A94D34", + rotation: 90, + blur: 10, + named: "some_name", + progressive: true, + lossless: true, + trim: 5, + metadata: true, + colorProfile: true, + defaultImage: "/folder/file.jpg/", + dpr: 3, + sharpen: 10, + unsharpMask: "2-2-0.8-0.024", + contrastStretch: true, + grayscale: true, + shadow: "bl-15_st-40_x-10_y-N5", + gradient: "from-red_to-white", + original: true, + raw: "h-200,w-300,l-image,i-logo.png,l-end" + } + ] + }); + + expect(url).toBe( + `https://ik.imagekit.io/test_url_endpoint/test_path.jpg?tr=h-300,w-400,ar-4-3,q-40,c-force,cm-extract,fo-left,f-jpeg,r-50,bg-A94D34,b-5-A94D34,rt-90,bl-10,n-some_name,pr-true,lo-true,t-5,md-true,cp-true,di-folder@@file.jpg,dpr-3,e-sharpen-10,e-usm-2-2-0.8-0.024,e-contrast,e-grayscale,e-shadow-bl-15_st-40_x-10_y-N5,e-gradient-from-red_to-white,orig-true,h-200,w-300,l-image,i-logo.png,l-end` + ); + }); + + test('should generate the correct URL with many transformations, including video and AI transforms', async ({ page }) => { + // Example test with comprehensive transformations + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + transformationPosition: "query", + src: "/test_path.jpg", + transformation: [ + { + height: 300, + width: 400, + aspectRatio: '4-3', + quality: 40, + crop: 'force', + cropMode: 'extract', + focus: 'left', + format: 'jpeg', + radius: 50, + bg: "A94D34", + border: "5-A94D34", + rotation: 90, + blur: 10, + named: "some_name", + progressive: true, + lossless: true, + trim: 5, + metadata: true, + colorProfile: true, + defaultImage: "/folder/file.jpg/", + dpr: 3, + x: 10, + y: 20, + xCenter: 30, + yCenter: 40, + flip: "h", + opacity: 0.8, + zoom: 2, + // Video transformations + videoCodec: "h264", + audioCodec: "aac", + startOffset: 5, + endOffset: 15, + duration: 10, + streamingResolutions: ["1440", "1080"], + // AI transformations + grayscale: true, + aiUpscale: true, + aiRetouch: true, + aiVariation: true, + aiDropShadow: true, + aiChangeBackground: "prompt-car", + aiEdit: 'prompt-make it vintage', + aiRemoveBackground: true, + contrastStretch: true, + shadow: "bl-15_st-40_x-10_y-N5", + sharpen: 10, + unsharpMask: "2-2-0.8-0.024", + gradient: "from-red_to-white", + original: true, + page: "2_4", + raw: "h-200,w-300,l-image,i-logo.png,l-end", + // New transformation parameters + colorReplace: 'FF0000_50_00FF00', + colorize: 'co-red_in-35', + distort: 'p-50_50_150_50_150_150_50_150', + } + ] + }); + + expect(url).toBe( + `https://ik.imagekit.io/test_url_endpoint/test_path.jpg?tr=h-300,w-400,ar-4-3,q-40,c-force,cm-extract,fo-left,f-jpeg,r-50,bg-A94D34,b-5-A94D34,rt-90,bl-10,n-some_name,pr-true,lo-true,t-5,md-true,cp-true,di-folder@@file.jpg,dpr-3,x-10,y-20,xc-30,yc-40,fl-h,o-0.8,z-2,vc-h264,ac-aac,so-5,eo-15,du-10,sr-1440_1080,e-grayscale,e-upscale,e-retouch,e-genvar,e-dropshadow,e-changebg-prompt-car,e-edit-prompt-make it vintage,e-bgremove,e-contrast,e-shadow-bl-15_st-40_x-10_y-N5,e-sharpen-10,e-usm-2-2-0.8-0.024,e-gradient-from-red_to-white,orig-true,pg-2_4,h-200,w-300,l-image,i-logo.png,l-end,cr-FF0000_50_00FF00,e-colorize-co-red_in-35,e-distort-p-50_50_150_50_150_150_50_150` + ); + }); +}); diff --git a/test-app/tests/buildTransformationString.spec.ts b/test-app/tests/buildTransformationString.spec.ts new file mode 100644 index 0000000..fdcc177 --- /dev/null +++ b/test-app/tests/buildTransformationString.spec.ts @@ -0,0 +1,27 @@ +import { test, expect } from "./fixtures"; + +test.describe("buildTransformationString", () => { + test("should return an empty string when no transformations are provided", async ({ page }) => { + const result = await page.evaluate(() => (window as any).buildTransformationString([{}])); + expect(result).toBe(""); + }); + + test("should generate a transformation string for width only", async ({ page }) => { + const result = await page.evaluate(() => (window as any).buildTransformationString([{ width: 300 }])); + expect(result).toBe("w-300"); + }); + + test("should generate a transformation string for multiple transformations", async ({ page }) => { + const result = await page.evaluate(() => + (window as any).buildTransformationString([ + { + overlay: { + type: "text", + text: "Hello", + }, + }, + ]), + ); + expect(result).toBe("l-text,i-Hello,l-end"); + }); +}); diff --git a/test-app/tests/fixtures.ts b/test-app/tests/fixtures.ts new file mode 100644 index 0000000..659ce07 --- /dev/null +++ b/test-app/tests/fixtures.ts @@ -0,0 +1,24 @@ +import { test as base, expect } from "@playwright/test"; + +/** + * Shared fixture for browser-based SDK tests. + * + * Each test runs the real built SDK bundle inside Chromium. The SDK functions + * are exposed on `window` by /test-app/index.html, so tests call them via + * `page.evaluate` and assert on the returned values. + */ +export const test = base.extend({ + page: async ({ page }, use) => { + await page.goto("/test-app/index.html"); + await page.waitForFunction( + () => + typeof (window as any).buildSrc === "function" && + typeof (window as any).buildTransformationString === "function" && + typeof (window as any).getResponsiveImageAttributes === "function", + ); + await use(page); + }, +}); + +export { expect }; + diff --git a/test-app/tests/overlay.spec.ts b/test-app/tests/overlay.spec.ts new file mode 100644 index 0000000..c3b5850 --- /dev/null +++ b/test-app/tests/overlay.spec.ts @@ -0,0 +1,459 @@ +import { test, expect } from "./fixtures"; + +async function buildSrc(page: import("@playwright/test").Page, opts: any): Promise { + return page.evaluate((o) => (window as any).buildSrc(o), opts); +} + +test.describe("Overlay Transformation Test Cases", () => { + test("Ignore invalid values if text is missing", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-image.jpg", + transformation: [{ overlay: { type: "text" } }], + }); + expect(url).toBe("https://ik.imagekit.io/test_url_endpoint/base-image.jpg"); + }); + + test("Ignore if type is missing", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-image.jpg", + transformation: [{ overlay: {} }], + }); + expect(url).toBe("https://ik.imagekit.io/test_url_endpoint/base-image.jpg"); + }); + + test("Ignore invalid values if input (image)", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-image.jpg", + transformation: [{ overlay: { type: "image" } }], + }); + expect(url).toBe("https://ik.imagekit.io/test_url_endpoint/base-image.jpg"); + }); + + test("Ignore invalid values if input (video)", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-image.jpg", + transformation: [{ overlay: { type: "video" } }], + }); + expect(url).toBe("https://ik.imagekit.io/test_url_endpoint/base-image.jpg"); + }); + + test("Ignore invalid values if input (subtitle)", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-image.jpg", + transformation: [{ overlay: { type: "subtitle" } }], + }); + expect(url).toBe("https://ik.imagekit.io/test_url_endpoint/base-image.jpg"); + }); + + test("Ignore invalid values if color is missing (solidColor)", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-image.jpg", + transformation: [{ overlay: { type: "solidColor" } }], + }); + expect(url).toBe("https://ik.imagekit.io/test_url_endpoint/base-image.jpg"); + }); + + test("Text overlay generates correct URL with encoded overlay text", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-image.jpg", + transformation: [{ overlay: { type: "text", text: "Minimal Text" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/test_url_endpoint/tr:l-text,i-Minimal%20Text,l-end/base-image.jpg", + ); + }); + + test("Image overlay generates correct URL with input logo.png", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-image.jpg", + transformation: [{ overlay: { type: "image", input: "logo.png" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/test_url_endpoint/tr:l-image,i-logo.png,l-end/base-image.jpg", + ); + }); + + test("Video overlay generates correct URL with input play-pause-loop.mp4", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-video.mp4", + transformation: [{ overlay: { type: "video", input: "play-pause-loop.mp4" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/test_url_endpoint/tr:l-video,i-play-pause-loop.mp4,l-end/base-video.mp4", + ); + }); + + test("Subtitle overlay generates correct URL with input subtitle.srt", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-video.mp4", + transformation: [{ overlay: { type: "subtitle", input: "subtitle.srt" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/test_url_endpoint/tr:l-subtitles,i-subtitle.srt,l-end/base-video.mp4", + ); + }); + + test("Solid color overlay generates correct URL with background color FF0000", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-image.jpg", + transformation: [{ overlay: { type: "solidColor", color: "FF0000" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/test_url_endpoint/tr:l-image,i-ik_canvas,bg-FF0000,l-end/base-image.jpg", + ); + }); + + test("Combined overlay transformations generate correct URL including nested overlays", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-image.jpg", + transformation: [ + { + overlay: { + type: "text", + text: "Every thing", + position: { x: "10", y: "20", focus: "center" }, + timing: { start: 5, duration: "10", end: 15 }, + transformation: [ + { + width: "bw_mul_0.5", + fontSize: 20, + fontFamily: "Arial", + fontColor: "0000ff", + innerAlignment: "left", + padding: 5, + alpha: 7, + typography: "b", + background: "red", + radius: 10, + rotation: "N45", + flip: "h", + lineHeight: 20, + }, + ], + }, + }, + { + overlay: { + type: "image", + input: "logo.png", + position: { x: "10", y: "20", focus: "center" }, + timing: { start: 5, duration: "10", end: 15 }, + transformation: [ + { + width: "bw_mul_0.5", + height: "bh_mul_0.5", + rotation: "N45", + flip: "h", + overlay: { type: "text", text: "Nested text overlay" }, + }, + ], + }, + }, + { + overlay: { + type: "video", + input: "play-pause-loop.mp4", + position: { x: "10", y: "20", focus: "center" }, + timing: { start: 5, duration: "10", end: 15 }, + transformations: [ + { width: "bw_mul_0.5", height: "bh_mul_0.5", rotation: "N45", flip: "h" }, + ], + }, + }, + { + overlay: { + type: "subtitle", + input: "subtitle.srt", + position: { x: "10", y: "20", focus: "center" }, + timing: { start: 5, duration: "10", end: 15 }, + transformations: [ + { width: "bw_mul_0.5", height: "bh_mul_0.5", rotation: "N45", flip: "h" }, + ], + }, + }, + { + overlay: { + type: "solidColor", + color: "FF0000", + position: { x: "10", y: "20", focus: "center" }, + timing: { start: 5, duration: "10", end: 15 }, + transformation: [ + { width: "bw_mul_0.5", height: "bh_mul_0.5", rotation: "N45", flip: "h" }, + ], + }, + }, + ], + }); + + expect(url).toBe( + "https://ik.imagekit.io/test_url_endpoint/tr:l-text,i-Every%20thing,lx-10,ly-20,lfo-center,lso-5,leo-15,ldu-10,w-bw_mul_0.5,fs-20,ff-Arial,co-0000ff,ia-left,pa-5,al-7,tg-b,bg-red,r-10,rt-N45,fl-h,lh-20,l-end:l-image,i-logo.png,lx-10,ly-20,lfo-center,lso-5,leo-15,ldu-10,w-bw_mul_0.5,h-bh_mul_0.5,rt-N45,fl-h,l-text,i-Nested%20text%20overlay,l-end,l-end:l-video,i-play-pause-loop.mp4,lx-10,ly-20,lfo-center,lso-5,leo-15,ldu-10,l-end:l-subtitles,i-subtitle.srt,lx-10,ly-20,lfo-center,lso-5,leo-15,ldu-10,l-end:l-image,i-ik_canvas,bg-FF0000,lx-10,ly-20,lfo-center,lso-5,leo-15,ldu-10,w-bw_mul_0.5,h-bh_mul_0.5,rt-N45,fl-h,l-end/base-image.jpg", + ); + }); +}); + +test.describe("Overlay encoding test cases", () => { + test("Nested simple path, should use i instead of ie, handle slash properly", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/demo", + src: "/medium_cafe_B1iTdD0C.jpg", + transformation: [{ overlay: { type: "image", input: "/customer_logo/nykaa.png" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/demo/tr:l-image,i-customer_logo@@nykaa.png,l-end/medium_cafe_B1iTdD0C.jpg", + ); + }); + + test("Nested non-simple path, should use ie instead of i", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/demo", + src: "/medium_cafe_B1iTdD0C.jpg", + transformation: [{ overlay: { type: "image", input: "/customer_logo/Ñykaa.png" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/demo/tr:l-image,ie-Y3VzdG9tZXJfbG9nby9OzIN5a2FhLnBuZw%3D%3D,l-end/medium_cafe_B1iTdD0C.jpg", + ); + }); + + test("Simple text overlay, should use i instead of ie", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/demo", + src: "/medium_cafe_B1iTdD0C.jpg", + transformation: [{ overlay: { type: "text", text: "Manu" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/demo/tr:l-text,i-Manu,l-end/medium_cafe_B1iTdD0C.jpg", + ); + }); + + test("Simple text overlay with spaces and other safe characters, should use i instead of ie", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/demo", + src: "/medium_cafe_B1iTdD0C.jpg", + transformation: [{ overlay: { type: "text", text: "alnum123-._ " } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/demo/tr:l-text,i-alnum123-._%20,l-end/medium_cafe_B1iTdD0C.jpg", + ); + }); + + test("Non simple text overlay, should use ie instead of i", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/demo", + src: "/medium_cafe_B1iTdD0C.jpg", + transformation: [{ overlay: { type: "text", text: "Let's use ©, ®, ™, etc" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/demo/tr:l-text,ie-TGV0J3MgdXNlIMKpLCDCriwg4oSiLCBldGM%3D,l-end/medium_cafe_B1iTdD0C.jpg", + ); + }); + + test("Text overlay with explicit plain encoding", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/demo", + src: "/sample.jpg", + transformation: [{ overlay: { type: "text", text: "HelloWorld", encoding: "plain" } }], + }); + expect(url).toBe("https://ik.imagekit.io/demo/tr:l-text,i-HelloWorld,l-end/sample.jpg"); + }); + + test("Text overlay with explicit base64 encoding", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/demo", + src: "/sample.jpg", + transformation: [{ overlay: { type: "text", text: "HelloWorld", encoding: "base64" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/demo/tr:l-text,ie-SGVsbG9Xb3JsZA%3D%3D,l-end/sample.jpg", + ); + }); + + test("Image overlay with explicit plain encoding", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/demo", + src: "/sample.jpg", + transformation: [{ overlay: { type: "image", input: "/customer/logo.png", encoding: "plain" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/demo/tr:l-image,i-customer@@logo.png,l-end/sample.jpg", + ); + }); + + test("Image overlay with explicit base64 encoding", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/demo", + src: "/sample.jpg", + transformation: [{ overlay: { type: "image", input: "/customer/logo.png", encoding: "base64" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/demo/tr:l-image,ie-Y3VzdG9tZXIvbG9nby5wbmc%3D,l-end/sample.jpg", + ); + }); + + test("Video overlay with explicit base64 encoding", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/demo", + src: "/sample.mp4", + transformation: [{ overlay: { type: "video", input: "/path/to/video.mp4", encoding: "base64" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/demo/tr:l-video,ie-cGF0aC90by92aWRlby5tcDQ%3D,l-end/sample.mp4", + ); + }); + + test("Subtitle overlay with explicit plain encoding", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/demo", + src: "/sample.mp4", + transformation: [{ overlay: { type: "subtitle", input: "/sub.srt", encoding: "plain" } }], + }); + expect(url).toBe("https://ik.imagekit.io/demo/tr:l-subtitles,i-sub.srt,l-end/sample.mp4"); + }); + + test("Subtitle overlay with explicit base64 encoding", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/demo", + src: "/sample.mp4", + transformation: [{ overlay: { type: "subtitle", input: "sub.srt", encoding: "base64" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/demo/tr:l-subtitles,ie-c3ViLnNydA%3D%3D,l-end/sample.mp4", + ); + }); + + test("Avoid double encoding when transformation string is in query params", async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/demo", + src: "/sample.jpg", + transformation: [{ overlay: { type: "text", text: "Minimal Text" } }], + transformationPosition: "query", + }); + expect(url).toBe("https://ik.imagekit.io/demo/sample.jpg?tr=l-text,i-Minimal%20Text,l-end"); + }); + + test.describe("Layer Mode Tests", () => { + test("should generate correct URL with multiply layer mode", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-image.jpg", + transformation: [{ overlay: { type: "image", input: "overlay-image.jpg", layerMode: "multiply" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/test_url_endpoint/tr:l-image,i-overlay-image.jpg,lm-multiply,l-end/base-image.jpg", + ); + }); + + test("should generate correct URL with cutter layer mode", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-image.jpg", + transformation: [{ overlay: { type: "image", input: "overlay-image.jpg", layerMode: "cutter" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/test_url_endpoint/tr:l-image,i-overlay-image.jpg,lm-cutter,l-end/base-image.jpg", + ); + }); + + test("should generate correct URL with cutout layer mode", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-image.jpg", + transformation: [{ overlay: { type: "image", input: "overlay-image.jpg", layerMode: "cutout" } }], + }); + expect(url).toBe( + "https://ik.imagekit.io/test_url_endpoint/tr:l-image,i-overlay-image.jpg,lm-cutout,l-end/base-image.jpg", + ); + }); + + test("should generate correct URL with displace layer mode", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-image.jpg", + transformation: [ + { overlay: { type: "image", input: "overlay-image.jpg", layerMode: "displace", position: { x: 10, y: 10 } } }, + ], + }); + expect(url).toBe( + "https://ik.imagekit.io/test_url_endpoint/tr:l-image,i-overlay-image.jpg,lm-displace,lx-10,ly-10,l-end/base-image.jpg", + ); + }); + + test("should generate correct URL with xCenter, yCenter and anchorPoint", async ({ page }) => { + const url = await buildSrc(page, { + transformationPosition: "path", + urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", + src: "/base-image.jpg", + transformation: [ + { overlay: { type: "image", input: "overlay-image.jpg", position: { xCenter: 100, yCenter: 50, anchorPoint: "top_left" } } }, + ], + }); + expect(url).toBe( + "https://ik.imagekit.io/test_url_endpoint/tr:l-image,i-overlay-image.jpg,lxc-100,lyc-50,lap-top_left,l-end/base-image.jpg", + ); + }); + }); + + test("should encode Hindi (non-ASCII) text overlay and base path", async ({ page }) => { + const url = await buildSrc(page, { + urlEndpoint: "https://ik.imagekit.io/demo/", + src: "sdk-testing-files/हिन्दी.png", + transformation: [ + { + overlay: { + type: "text", + text: "हिन्दी", + transformation: [ + { + fontColor: "red", + fontSize: "32", + fontFamily: "sdk-testing-files/Poppins-Regular_Q15GrYWmL.ttf", + }, + ], + }, + }, + ], + }); + expect(url).toBe( + "https://ik.imagekit.io/demo/sdk-testing-files/%E0%A4%B9%E0%A4%BF%E0%A4%A8%E0%A5%8D%E0%A4%A6%E0%A5%80.png?tr=l-text,ie-4KS54KS%2F4KSo4KWN4KSm4KWA,co-red,fs-32,ff-sdk-testing-files@@Poppins-Regular_Q15GrYWmL.ttf,l-end", + ); + }); +}); diff --git a/test-app/tests/responsive.spec.ts b/test-app/tests/responsive.spec.ts new file mode 100644 index 0000000..061d9db --- /dev/null +++ b/test-app/tests/responsive.spec.ts @@ -0,0 +1,154 @@ +import { test, expect } from "./fixtures"; + +async function getResponsiveImageAttributes(page: import("@playwright/test").Page, opts: any) { + return page.evaluate((o) => (window as any).getResponsiveImageAttributes(o), opts); +} + +test.describe("getResponsiveImageAttributes", () => { + test("bare minimum input", async ({ page }) => { + const out = await getResponsiveImageAttributes(page, { + src: "sample.jpg", + urlEndpoint: "https://ik.imagekit.io/demo", + }); + expect(out).toEqual({ + src: "https://ik.imagekit.io/demo/sample.jpg?tr=w-3840,c-at_max", + srcSet: + "https://ik.imagekit.io/demo/sample.jpg?tr=w-640,c-at_max 640w, https://ik.imagekit.io/demo/sample.jpg?tr=w-750,c-at_max 750w, https://ik.imagekit.io/demo/sample.jpg?tr=w-828,c-at_max 828w, https://ik.imagekit.io/demo/sample.jpg?tr=w-1080,c-at_max 1080w, https://ik.imagekit.io/demo/sample.jpg?tr=w-1200,c-at_max 1200w, https://ik.imagekit.io/demo/sample.jpg?tr=w-1920,c-at_max 1920w, https://ik.imagekit.io/demo/sample.jpg?tr=w-2048,c-at_max 2048w, https://ik.imagekit.io/demo/sample.jpg?tr=w-3840,c-at_max 3840w", + sizes: "100vw", + }); + }); + + test("sizes provided (100vw)", async ({ page }) => { + const out = await getResponsiveImageAttributes(page, { + src: "sample.jpg", + urlEndpoint: "https://ik.imagekit.io/demo", + sizes: "100vw", + }); + expect(out).toEqual({ + src: "https://ik.imagekit.io/demo/sample.jpg?tr=w-3840,c-at_max", + srcSet: + "https://ik.imagekit.io/demo/sample.jpg?tr=w-640,c-at_max 640w, https://ik.imagekit.io/demo/sample.jpg?tr=w-750,c-at_max 750w, https://ik.imagekit.io/demo/sample.jpg?tr=w-828,c-at_max 828w, https://ik.imagekit.io/demo/sample.jpg?tr=w-1080,c-at_max 1080w, https://ik.imagekit.io/demo/sample.jpg?tr=w-1200,c-at_max 1200w, https://ik.imagekit.io/demo/sample.jpg?tr=w-1920,c-at_max 1920w, https://ik.imagekit.io/demo/sample.jpg?tr=w-2048,c-at_max 2048w, https://ik.imagekit.io/demo/sample.jpg?tr=w-3840,c-at_max 3840w", + sizes: "100vw", + }); + }); + + test("width only – DPR strategy", async ({ page }) => { + const out = await getResponsiveImageAttributes(page, { + src: "sample.jpg", + urlEndpoint: "https://ik.imagekit.io/demo", + width: 400, + }); + expect(out).toEqual({ + src: "https://ik.imagekit.io/demo/sample.jpg?tr=w-828,c-at_max", + srcSet: + "https://ik.imagekit.io/demo/sample.jpg?tr=w-640,c-at_max 1x, https://ik.imagekit.io/demo/sample.jpg?tr=w-828,c-at_max 2x", + width: 400, + }); + }); + + test("custom breakpoints", async ({ page }) => { + const out = await getResponsiveImageAttributes(page, { + src: "sample.jpg", + urlEndpoint: "https://ik.imagekit.io/demo", + deviceBreakpoints: [200, 400, 800], + imageBreakpoints: [100], + }); + expect(out).toEqual({ + src: "https://ik.imagekit.io/demo/sample.jpg?tr=w-800,c-at_max", + srcSet: + "https://ik.imagekit.io/demo/sample.jpg?tr=w-200,c-at_max 200w, https://ik.imagekit.io/demo/sample.jpg?tr=w-400,c-at_max 400w, https://ik.imagekit.io/demo/sample.jpg?tr=w-800,c-at_max 800w", + sizes: "100vw", + }); + }); + + test("preserves caller transformations", async ({ page }) => { + const out = await getResponsiveImageAttributes(page, { + src: "sample.jpg", + urlEndpoint: "https://ik.imagekit.io/demo", + width: 500, + transformation: [{ height: 300 }], + }); + expect(out).toEqual({ + src: "https://ik.imagekit.io/demo/sample.jpg?tr=h-300:w-1080,c-at_max", + srcSet: + "https://ik.imagekit.io/demo/sample.jpg?tr=h-300:w-640,c-at_max 1x, https://ik.imagekit.io/demo/sample.jpg?tr=h-300:w-1080,c-at_max 2x", + width: 500, + }); + }); + + test("both sizes and width passed", async ({ page }) => { + const out = await getResponsiveImageAttributes(page, { + src: "sample.jpg", + urlEndpoint: "https://ik.imagekit.io/demo", + sizes: "50vw", + width: 600, + }); + expect(out).toEqual({ + src: "https://ik.imagekit.io/demo/sample.jpg?tr=w-3840,c-at_max", + srcSet: + "https://ik.imagekit.io/demo/sample.jpg?tr=w-384,c-at_max 384w, https://ik.imagekit.io/demo/sample.jpg?tr=w-640,c-at_max 640w, https://ik.imagekit.io/demo/sample.jpg?tr=w-750,c-at_max 750w, https://ik.imagekit.io/demo/sample.jpg?tr=w-828,c-at_max 828w, https://ik.imagekit.io/demo/sample.jpg?tr=w-1080,c-at_max 1080w, https://ik.imagekit.io/demo/sample.jpg?tr=w-1200,c-at_max 1200w, https://ik.imagekit.io/demo/sample.jpg?tr=w-1920,c-at_max 1920w, https://ik.imagekit.io/demo/sample.jpg?tr=w-2048,c-at_max 2048w, https://ik.imagekit.io/demo/sample.jpg?tr=w-3840,c-at_max 3840w", + sizes: "50vw", + width: 600, + }); + }); + + test("multiple transformations", async ({ page }) => { + const out = await getResponsiveImageAttributes(page, { + src: "sample.jpg", + urlEndpoint: "https://ik.imagekit.io/demo", + width: 450, + transformation: [{ height: 300 }, { aiRemoveBackground: true }], + }); + expect(out).toEqual({ + src: "https://ik.imagekit.io/demo/sample.jpg?tr=h-300:e-bgremove:w-1080,c-at_max", + srcSet: + "https://ik.imagekit.io/demo/sample.jpg?tr=h-300:e-bgremove:w-640,c-at_max 1x, https://ik.imagekit.io/demo/sample.jpg?tr=h-300:e-bgremove:w-1080,c-at_max 2x", + width: 450, + }); + }); + + test("sizes causes breakpoint pruning (33vw path)", async ({ page }) => { + const out = await getResponsiveImageAttributes(page, { + src: "sample.jpg", + urlEndpoint: "https://ik.imagekit.io/demo", + sizes: "(min-width: 800px) 33vw, 100vw", + }); + expect(out).toEqual({ + src: "https://ik.imagekit.io/demo/sample.jpg?tr=w-3840,c-at_max", + srcSet: + "https://ik.imagekit.io/demo/sample.jpg?tr=w-256,c-at_max 256w, https://ik.imagekit.io/demo/sample.jpg?tr=w-384,c-at_max 384w, https://ik.imagekit.io/demo/sample.jpg?tr=w-640,c-at_max 640w, https://ik.imagekit.io/demo/sample.jpg?tr=w-750,c-at_max 750w, https://ik.imagekit.io/demo/sample.jpg?tr=w-828,c-at_max 828w, https://ik.imagekit.io/demo/sample.jpg?tr=w-1080,c-at_max 1080w, https://ik.imagekit.io/demo/sample.jpg?tr=w-1200,c-at_max 1200w, https://ik.imagekit.io/demo/sample.jpg?tr=w-1920,c-at_max 1920w, https://ik.imagekit.io/demo/sample.jpg?tr=w-2048,c-at_max 2048w, https://ik.imagekit.io/demo/sample.jpg?tr=w-3840,c-at_max 3840w", + sizes: "(min-width: 800px) 33vw, 100vw", + }); + }); + + test("Using queryParameters and transformationPosition", async ({ page }) => { + const out = await getResponsiveImageAttributes(page, { + src: "sample.jpg", + urlEndpoint: "https://ik.imagekit.io/demo", + width: 450, + transformation: [{ height: 300 }, { aiRemoveBackground: true }], + queryParameters: { key: "value" }, + transformationPosition: "path", + }); + expect(out).toEqual({ + src: "https://ik.imagekit.io/demo/tr:h-300:e-bgremove:w-1080,c-at_max/sample.jpg?key=value", + srcSet: + "https://ik.imagekit.io/demo/tr:h-300:e-bgremove:w-640,c-at_max/sample.jpg?key=value 1x, https://ik.imagekit.io/demo/tr:h-300:e-bgremove:w-1080,c-at_max/sample.jpg?key=value 2x", + width: 450, + }); + }); + + test("fallback when no usable vw tokens", async ({ page }) => { + const out = await getResponsiveImageAttributes(page, { + src: "sample.jpg", + urlEndpoint: "https://ik.imagekit.io/demo", + sizes: "100%", + }); + expect(out).toEqual({ + src: "https://ik.imagekit.io/demo/sample.jpg?tr=w-3840,c-at_max", + srcSet: + "https://ik.imagekit.io/demo/sample.jpg?tr=w-16,c-at_max 16w, https://ik.imagekit.io/demo/sample.jpg?tr=w-32,c-at_max 32w, https://ik.imagekit.io/demo/sample.jpg?tr=w-48,c-at_max 48w, https://ik.imagekit.io/demo/sample.jpg?tr=w-64,c-at_max 64w, https://ik.imagekit.io/demo/sample.jpg?tr=w-96,c-at_max 96w, https://ik.imagekit.io/demo/sample.jpg?tr=w-128,c-at_max 128w, https://ik.imagekit.io/demo/sample.jpg?tr=w-256,c-at_max 256w, https://ik.imagekit.io/demo/sample.jpg?tr=w-384,c-at_max 384w, https://ik.imagekit.io/demo/sample.jpg?tr=w-640,c-at_max 640w, https://ik.imagekit.io/demo/sample.jpg?tr=w-750,c-at_max 750w, https://ik.imagekit.io/demo/sample.jpg?tr=w-828,c-at_max 828w, https://ik.imagekit.io/demo/sample.jpg?tr=w-1080,c-at_max 1080w, https://ik.imagekit.io/demo/sample.jpg?tr=w-1200,c-at_max 1200w, https://ik.imagekit.io/demo/sample.jpg?tr=w-1920,c-at_max 1920w, https://ik.imagekit.io/demo/sample.jpg?tr=w-2048,c-at_max 2048w, https://ik.imagekit.io/demo/sample.jpg?tr=w-3840,c-at_max 3840w", + sizes: "100%", + }); + }); +}); diff --git a/test-app/tests/upload.spec.ts b/test-app/tests/upload.spec.ts new file mode 100644 index 0000000..67ff9a5 --- /dev/null +++ b/test-app/tests/upload.spec.ts @@ -0,0 +1,1241 @@ +import { test, expect } from "./fixtures"; +import type { Page, Route } from "@playwright/test"; + +/** + * Upload tests run the real built SDK inside Chromium. Instead of sinon's fake + * XMLHttpRequest, the actual upload request is captured and answered with + * Playwright network interception (`page.route`). The multipart body is parsed + * back into its FormData fields so we can assert exactly what the SDK sent. + */ + +const UPLOAD_URL = "https://upload.imagekit.io/api/v1/files/upload"; + +const uploadSuccessResponseObj = { + fileId: "598821f949c0a938d57563bd", + name: "file1.jpg", + url: "https://ik.imagekit.io/your_imagekit_id/images/products/file1.jpg", + thumbnailUrl: + "https://ik.imagekit.io/your_imagekit_id/tr:n-media_library_thumbnail/images/products/file1.jpg", + height: 300, + width: 200, + size: 83622, + filePath: "/images/products/file1.jpg", + tags: ["t-shirt", "round-neck", "sale2019"], + isPrivateFile: false, + customCoordinates: null, + fileType: "image", + AITags: [{ name: "Face", confidence: 99.95, source: "aws-auto-tagging" }], + extensionStatus: { "aws-auto-tagging": "success" }, +}; + +const securityParameters = { + signature: "test_signature", + expire: 123, + token: "test_token", + publicKey: "test_public_key", +}; + +/** Parse a multipart/form-data body into its text fields. */ +function parseMultipart( + buffer: Buffer | null, + contentType: string, +): Record { + const fields: Record = {}; + if (!buffer) return fields; + const boundaryMatch = /boundary=(.+)$/.exec(contentType); + if (!boundaryMatch) return fields; + const boundary = "--" + boundaryMatch[1]; + // latin1 keeps a 1:1 byte mapping so byte lengths stay accurate. + const raw = buffer.toString("latin1"); + for (const part of raw.split(boundary)) { + const headerEnd = part.indexOf("\r\n\r\n"); + if (headerEnd === -1) continue; + const header = part.slice(0, headerEnd); + const nameMatch = /name="([^"]*)"/.exec(header); + if (!nameMatch) continue; + fields[nameMatch[1]] = part.slice(headerEnd + 4).replace(/\r\n$/, ""); + } + return fields; +} + +type MockOptions = { + status?: number; + headers?: Record; + body?: string; + /** Reject the request at the network layer (triggers xhr.onerror). */ + networkError?: boolean; + /** Never answer the request (used for client-side abort tests). */ + hang?: boolean; +}; + +type Mock = { + fields: () => Record; + count: () => number; +}; + +/** Install a route that captures the upload payload and returns a mock response. */ +async function mockUpload(page: Page, options: MockOptions = {}): Promise { + let captured: Record = {}; + let count = 0; + await page.route(UPLOAD_URL, async (route: Route) => { + count++; + const request = route.request(); + captured = parseMultipart( + request.postDataBuffer(), + request.headers()["content-type"] || "", + ); + if (options.hang) return; // leave the request pending for abort tests + if (options.networkError) { + await route.abort("failed"); + return; + } + await route.fulfill({ + status: options.status ?? 200, + headers: { + "access-control-allow-origin": "*", + "content-type": "application/json", + ...(options.headers || {}), + }, + body: options.body ?? JSON.stringify(uploadSuccessResponseObj), + }); + }); + return { fields: () => captured, count: () => count }; +} + +type UploadResult = + | { ok: true; response: any } + | { + ok: false; + error: { + name: string; + message: string; + isAbort: boolean; + isInvalid: boolean; + isServer: boolean; + isNetwork: boolean; + isSyntax: boolean; + }; + }; + +/** Call the SDK `upload` in the browser and return a serializable result. */ +async function runUpload(page: Page, opts: any): Promise { + return page.evaluate(async (o) => { + const w = window as any; + try { + const response = await w.upload(o); + return { ok: true as const, response }; + } catch (e: any) { + return { + ok: false as const, + error: { + name: e?.name, + message: e?.message, + isAbort: e instanceof w.ImageKitAbortError, + isInvalid: e instanceof w.ImageKitInvalidRequestError, + isServer: e instanceof w.ImageKitServerError, + isNetwork: e instanceof w.ImageKitUploadNetworkError, + isSyntax: e instanceof SyntaxError, + }, + }; + } + }, opts); +} + +test.describe("File upload", () => { + test("Invalid options", async ({ page }) => { + const result = await runUpload(page, undefined); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isInvalid).toBe(true); + expect(result.error.message).toBe("Invalid options provided for upload"); + }); + + test("Missing fileName", async ({ page }) => { + const result = await runUpload(page, { + ...securityParameters, + file: "https://ik.imagekit.io/remote-url.jpg", + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isInvalid).toBe(true); + expect(result.error.message).toBe("Missing fileName parameter for upload"); + }); + + test("Missing file", async ({ page }) => { + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isInvalid).toBe(true); + expect(result.error.message).toBe("Missing file parameter for upload"); + }); + + test("Missing token", async ({ page }) => { + const result = await runUpload(page, { + fileName: "test_file_name", + file: "test_file", + signature: "test_signature", + expire: 123, + publicKey: "test_public_key", + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isInvalid).toBe(true); + expect(result.error.message).toBe( + "Missing token for upload. The SDK expects token, signature and expire for authentication.", + ); + }); + + test("Missing signature", async ({ page }) => { + const result = await runUpload(page, { + fileName: "test_file_name", + file: "test_file", + token: "test_token", + expire: 123, + publicKey: "test_public_key", + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isInvalid).toBe(true); + expect(result.error.message).toBe( + "Missing signature for upload. The SDK expects token, signature and expire for authentication.", + ); + }); + + test("Missing expire", async ({ page }) => { + const result = await runUpload(page, { + fileName: "test_file_name", + file: "test_file", + token: "test_token", + signature: "test_signature", + publicKey: "test_public_key", + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isInvalid).toBe(true); + expect(result.error.message).toBe( + "Missing expire for upload. The SDK expects token, signature and expire for authentication.", + ); + }); + + test("Missing public key", async ({ page }) => { + const result = await runUpload(page, { + fileName: "test_file_name", + file: "test_file", + token: "test_token", + signature: "test_signature", + expire: 123, + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isInvalid).toBe(true); + expect(result.error.message).toBe("Missing public key for upload"); + }); + + test("Upload endpoint network error handling", async ({ page }) => { + await mockUpload(page, { networkError: true }); + const result = await runUpload(page, { + fileName: "test_file_name", + file: "test_file", + token: "test_token", + signature: "test_signature", + expire: 123, + publicKey: "test_public_key", + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isNetwork).toBe(true); + expect(result.error.message).toBe( + "Request to ImageKit upload endpoint failed due to network error", + ); + }); + + test("Boolean handling", async ({ page }) => { + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + tags: "test_tag1,test_tag2", + customCoordinates: "10, 10, 100, 100", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + isPrivateFile: true, + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + expect(mock.count()).toBe(1); + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.token).toBe("test_token"); + expect(f.expire).toBe("123"); + expect(f.signature).toBe("test_signature"); + expect(f.tags).toBe("test_tag1,test_tag2"); + expect(f.customCoordinates).toBe("10, 10, 100, 100"); + expect(f.responseFields).toBe("tags, customCoordinates, isPrivateFile, metadata"); + expect(f.useUniqueFileName).toBe("false"); + expect(f.isPrivateFile).toBe("true"); + expect(f.publicKey).toBe("test_public_key"); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("Tag array handling", async ({ page }) => { + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + tags: ["test_tag1", "test_tag2"], + useUniqueFileName: false, + isPrivateFile: true, + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + expect(mock.count()).toBe(1); + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.token).toBe("test_token"); + expect(f.expire).toBe("123"); + expect(f.signature).toBe("test_signature"); + expect(f.tags).toBe("test_tag1,test_tag2"); + expect(f.useUniqueFileName).toBe("false"); + expect(f.isPrivateFile).toBe("true"); + expect(f.publicKey).toBe("test_public_key"); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("Missing useUniqueFileName", async ({ page }) => { + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + tags: ["test_tag1", "test_tag2"], + isPrivateFile: true, + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.token).toBe("test_token"); + expect(f.expire).toBe("123"); + expect(f.signature).toBe("test_signature"); + expect(f.tags).toBe("test_tag1,test_tag2"); + expect(f.isPrivateFile).toBe("true"); + expect(f.publicKey).toBe("test_public_key"); + expect(f.useUniqueFileName).toBeUndefined(); + expect(f.customCoordinates).toBeUndefined(); + expect(f.responseFields).toBeUndefined(); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("Missing isPrivateFile", async ({ page }) => { + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + tags: ["test_tag1", "test_tag2"], + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.token).toBe("test_token"); + expect(f.expire).toBe("123"); + expect(f.signature).toBe("test_signature"); + expect(f.tags).toBe("test_tag1,test_tag2"); + expect(f.publicKey).toBe("test_public_key"); + expect(f.isPrivateFile).toBeUndefined(); + expect(f.useUniqueFileName).toBeUndefined(); + expect(f.customCoordinates).toBeUndefined(); + expect(f.responseFields).toBeUndefined(); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("With extensions parameter", async ({ page }) => { + const extensions = [{ name: "aws-auto-tagging", minConfidence: 80, maxTags: 10 }]; + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + tags: "test_tag1,test_tag2", + customCoordinates: "10, 10, 100, 100", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + isPrivateFile: true, + extensions, + webhookUrl: "https://your-domain/?appId=some-id", + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.token).toBe("test_token"); + expect(f.expire).toBe("123"); + expect(f.signature).toBe("test_signature"); + expect(f.tags).toBe("test_tag1,test_tag2"); + expect(f.customCoordinates).toBe("10, 10, 100, 100"); + expect(f.responseFields).toBe("tags, customCoordinates, isPrivateFile, metadata"); + expect(f.useUniqueFileName).toBe("false"); + expect(f.isPrivateFile).toBe("true"); + expect(f.publicKey).toBe("test_public_key"); + expect(f.extensions).toBe(JSON.stringify(extensions)); + expect(f.webhookUrl).toBe("https://your-domain/?appId=some-id"); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("Bare minimum request", async ({ page }) => { + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + tags: undefined, + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.token).toBe("test_token"); + expect(f.expire).toBe("123"); + expect(f.signature).toBe("test_signature"); + expect(f.publicKey).toBe("test_public_key"); + expect(f.tags).toBeUndefined(); + expect(f.isPrivateFile).toBeUndefined(); + expect(f.useUniqueFileName).toBeUndefined(); + expect(f.customCoordinates).toBeUndefined(); + expect(f.responseFields).toBeUndefined(); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("Bare minimum request: Blob", async ({ page }) => { + const mock = await mockUpload(page); + const result = await page.evaluate(async (sec) => { + const w = window as any; + const file = new Blob(["test_buffer"]); + try { + const response = await w.upload({ + ...sec, + fileName: "test_file_name", + file, + }); + return { ok: true as const, response }; + } catch (e: any) { + return { ok: false as const, message: e?.message }; + } + }, securityParameters); + expect(result.ok).toBe(true); + if (!result.ok) return; + + const f = mock.fields(); + // Blob content is sent as the raw bytes of "test_buffer" (11 bytes). + expect(Buffer.byteLength(f.file, "latin1")).toBe("test_buffer".length); + expect(f.fileName).toBe("test_file_name"); + expect(f.token).toBe("test_token"); + expect(f.expire).toBe("123"); + expect(f.signature).toBe("test_signature"); + expect(f.publicKey).toBe("test_public_key"); + expect(f.tags).toBeUndefined(); + expect(f.isPrivateFile).toBeUndefined(); + expect(f.useUniqueFileName).toBeUndefined(); + expect(f.customCoordinates).toBeUndefined(); + expect(f.responseFields).toBeUndefined(); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("Error during upload", async ({ page }) => { + await mockUpload(page, { + status: 401, + body: JSON.stringify({ + help: "For support kindly contact us at support@imagekit.io .", + message: "Your account cannot be authenticated.", + }), + }); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isInvalid).toBe(true); + expect(result.error.message).toBe("Your account cannot be authenticated."); + }); + + test("Error during upload non 2xx with bad body", async ({ page }) => { + await mockUpload(page, { status: 500, body: "sdf" }); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isServer).toBe(true); + expect(result.error.message).toBe( + "Server error occurred while uploading the file. This is rare and usually temporary.", + ); + }); + + test("Error during upload 2xx with bad body", async ({ page }) => { + await mockUpload(page, { status: 200, body: "sdf" }); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isSyntax).toBe(true); + }); + + test("Upload via URL", async ({ page }) => { + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "https://ik.imagekit.io/remote-url.jpg", + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + + const f = mock.fields(); + expect(f.file).toBe("https://ik.imagekit.io/remote-url.jpg"); + expect(f.fileName).toBe("test_file_name"); + expect(f.token).toBe("test_token"); + expect(f.expire).toBe("123"); + expect(f.signature).toBe("test_signature"); + expect(f.publicKey).toBe("test_public_key"); + expect(f.tags).toBeUndefined(); + expect(f.isPrivateFile).toBeUndefined(); + expect(f.useUniqueFileName).toBeUndefined(); + expect(f.customCoordinates).toBeUndefined(); + expect(f.responseFields).toBeUndefined(); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("Overriding public key", async ({ page }) => { + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "https://ik.imagekit.io/remote-url.jpg", + publicKey: "override_public_key", + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + + const f = mock.fields(); + expect(f.file).toBe("https://ik.imagekit.io/remote-url.jpg"); + expect(f.fileName).toBe("test_file_name"); + expect(f.token).toBe("test_token"); + expect(f.expire).toBe("123"); + expect(f.signature).toBe("test_signature"); + expect(f.publicKey).toBe("override_public_key"); + expect(f.tags).toBeUndefined(); + expect(f.isPrivateFile).toBeUndefined(); + expect(f.useUniqueFileName).toBeUndefined(); + expect(f.customCoordinates).toBeUndefined(); + expect(f.responseFields).toBeUndefined(); + expect(f.extensions).toBeUndefined(); + expect(f.customMetadata).toBeUndefined(); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("With overwrite parameters", async ({ page }) => { + const extensions = [{ name: "aws-auto-tagging", minConfidence: 80, maxTags: 10 }]; + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + tags: "test_tag1,test_tag2", + customCoordinates: "10, 10, 100, 100", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + isPrivateFile: true, + extensions, + overwriteFile: false, + overwriteAITags: false, + overwriteTags: false, + overwriteCustomMetadata: false, + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.token).toBe("test_token"); + expect(f.expire).toBe("123"); + expect(f.signature).toBe("test_signature"); + expect(f.tags).toBe("test_tag1,test_tag2"); + expect(f.customCoordinates).toBe("10, 10, 100, 100"); + expect(f.responseFields).toBe("tags, customCoordinates, isPrivateFile, metadata"); + expect(f.useUniqueFileName).toBe("false"); + expect(f.isPrivateFile).toBe("true"); + expect(f.publicKey).toBe("test_public_key"); + expect(f.extensions).toBe(JSON.stringify(extensions)); + expect(f.overwriteFile).toBe("false"); + expect(f.overwriteAITags).toBe("false"); + expect(f.overwriteTags).toBe("false"); + expect(f.overwriteCustomMetadata).toBe("false"); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("With customMetadata", async ({ page }) => { + const extensions = [{ name: "aws-auto-tagging", minConfidence: 80, maxTags: 10 }]; + const customMetadata = { brand: "Nike", color: "red" }; + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + tags: "test_tag1,test_tag2", + customCoordinates: "10, 10, 100, 100", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + isPrivateFile: true, + extensions, + overwriteFile: false, + overwriteAITags: false, + overwriteTags: false, + overwriteCustomMetadata: false, + customMetadata, + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.token).toBe("test_token"); + expect(f.expire).toBe("123"); + expect(f.signature).toBe("test_signature"); + expect(f.tags).toBe("test_tag1,test_tag2"); + expect(f.customCoordinates).toBe("10, 10, 100, 100"); + expect(f.responseFields).toBe("tags, customCoordinates, isPrivateFile, metadata"); + expect(f.useUniqueFileName).toBe("false"); + expect(f.isPrivateFile).toBe("true"); + expect(f.publicKey).toBe("test_public_key"); + expect(f.extensions).toBe(JSON.stringify(extensions)); + expect(f.overwriteFile).toBe("false"); + expect(f.overwriteAITags).toBe("false"); + expect(f.overwriteTags).toBe("false"); + expect(f.overwriteCustomMetadata).toBe("false"); + expect(f.customMetadata).toBe(JSON.stringify(customMetadata)); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("Array type fields", async ({ page }) => { + const extensions = [{ name: "aws-auto-tagging", minConfidence: 80, maxTags: 10 }]; + const customMetadata = { brand: "Nike", color: "red" }; + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + tags: ["test_tag1", "test_tag2"], + customCoordinates: "10, 10, 100, 100", + responseFields: ["tags", "customCoordinates", "isPrivateFile", "metadata"], + useUniqueFileName: false, + isPrivateFile: true, + extensions, + overwriteFile: false, + overwriteAITags: false, + overwriteTags: false, + overwriteCustomMetadata: false, + customMetadata, + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.token).toBe("test_token"); + expect(f.expire).toBe("123"); + expect(f.signature).toBe("test_signature"); + expect(f.tags).toBe("test_tag1,test_tag2"); + expect(f.customCoordinates).toBe("10, 10, 100, 100"); + expect(f.responseFields).toBe("tags,customCoordinates,isPrivateFile,metadata"); + expect(f.useUniqueFileName).toBe("false"); + expect(f.isPrivateFile).toBe("true"); + expect(f.publicKey).toBe("test_public_key"); + expect(f.extensions).toBe(JSON.stringify(extensions)); + expect(f.overwriteFile).toBe("false"); + expect(f.overwriteAITags).toBe("false"); + expect(f.overwriteTags).toBe("false"); + expect(f.overwriteCustomMetadata).toBe("false"); + expect(f.customMetadata).toBe(JSON.stringify(customMetadata)); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("check custom XHR object is used", async ({ page }) => { + const extensions = [{ name: "aws-auto-tagging", minConfidence: 80, maxTags: 10 }]; + const mock = await mockUpload(page); + const out = await page.evaluate(async (opts) => { + const w = window as any; + const xhr = new XMLHttpRequest(); + const fun = function () { + return "hello from function"; + }; + xhr.onprogress = fun as any; + try { + const response = await w.upload({ ...opts, xhr }); + return { + ok: true as const, + status: xhr.status, + onprogressPreserved: xhr.onprogress === (fun as any), + response, + }; + } catch (e: any) { + return { ok: false as const, message: e?.message }; + } + }, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + tags: "test_tag1,test_tag2", + customCoordinates: "10, 10, 100, 100", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + isPrivateFile: true, + extensions, + }); + expect(out.ok).toBe(true); + if (!out.ok) return; + // The provided xhr instance carried out the request and kept its handler. + expect(out.status).toBe(200); + expect(out.onprogressPreserved).toBe(true); + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.token).toBe("test_token"); + expect(f.expire).toBe("123"); + expect(f.signature).toBe("test_signature"); + expect(f.tags).toBe("test_tag1,test_tag2"); + expect(f.customCoordinates).toBe("10, 10, 100, 100"); + expect(f.responseFields).toBe("tags, customCoordinates, isPrivateFile, metadata"); + expect(f.useUniqueFileName).toBe("false"); + expect(f.isPrivateFile).toBe("true"); + expect(f.publicKey).toBe("test_public_key"); + expect(f.extensions).toBe(JSON.stringify(extensions)); + expect(out.response).toEqual(uploadSuccessResponseObj); + }); + + test("Upload using promise - success", async ({ page }) => { + const extensions = [{ name: "aws-auto-tagging", minConfidence: 80, maxTags: 10 }]; + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + tags: "test_tag1,test_tag2", + customCoordinates: "10, 10, 100, 100", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + isPrivateFile: true, + extensions, + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.token).toBe("test_token"); + expect(f.expire).toBe("123"); + expect(f.signature).toBe("test_signature"); + expect(f.tags).toBe("test_tag1,test_tag2"); + expect(f.customCoordinates).toBe("10, 10, 100, 100"); + expect(f.responseFields).toBe("tags, customCoordinates, isPrivateFile, metadata"); + expect(f.useUniqueFileName).toBe("false"); + expect(f.isPrivateFile).toBe("true"); + expect(f.publicKey).toBe("test_public_key"); + expect(f.extensions).toBe(JSON.stringify(extensions)); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("Server 5xx error with proper json and message", async ({ page }) => { + const extensions = [{ name: "aws-auto-tagging", minConfidence: 80, maxTags: 10 }]; + await mockUpload(page, { + status: 500, + body: JSON.stringify({ + help: "For support kindly contact us at support@imagekit.io .", + message: "Something went wrong", + }), + }); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + tags: "test_tag1,test_tag2", + customCoordinates: "10, 10, 100, 100", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + isPrivateFile: true, + extensions, + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isServer).toBe(true); + expect(result.error.message).toBe("Something went wrong"); + }); + + test("Custom xhr promise", async ({ page }) => { + const extensions = [{ name: "aws-auto-tagging", minConfidence: 80, maxTags: 10 }]; + const mock = await mockUpload(page); + const out = await page.evaluate(async (opts) => { + const w = window as any; + const xhr = new XMLHttpRequest(); + const fun = function () { + return "hello from function"; + }; + xhr.onprogress = fun as any; + try { + const response = await w.upload({ ...opts, xhr }); + return { + ok: true as const, + status: xhr.status, + onprogressPreserved: xhr.onprogress === (fun as any), + response, + }; + } catch (e: any) { + return { ok: false as const, message: e?.message }; + } + }, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + tags: "test_tag1,test_tag2", + customCoordinates: "10, 10, 100, 100", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + isPrivateFile: true, + extensions, + }); + expect(out.ok).toBe(true); + if (!out.ok) return; + expect(out.status).toBe(200); + expect(out.onprogressPreserved).toBe(true); + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.token).toBe("test_token"); + expect(f.expire).toBe("123"); + expect(f.signature).toBe("test_signature"); + expect(f.tags).toBe("test_tag1,test_tag2"); + expect(f.customCoordinates).toBe("10, 10, 100, 100"); + expect(f.responseFields).toBe("tags, customCoordinates, isPrivateFile, metadata"); + expect(f.useUniqueFileName).toBe("false"); + expect(f.isPrivateFile).toBe("true"); + expect(f.publicKey).toBe("test_public_key"); + expect(f.extensions).toBe(JSON.stringify(extensions)); + expect(out.response).toEqual(uploadSuccessResponseObj); + }); + + test("$ResponseMetadata assertions using promise", async ({ page }) => { + const extensions = [{ name: "aws-auto-tagging", minConfidence: 80, maxTags: 10 }]; + await mockUpload(page, { + status: 200, + headers: { + "content-type": "application/json", + "x-request-id": "sdfsdfsdfdsf", + // Expose the custom header so the cross-origin XHR can read it back. + "access-control-expose-headers": "x-request-id", + }, + body: JSON.stringify(uploadSuccessResponseObj), + }); + const meta = await page.evaluate(async (opts) => { + const w = window as any; + const response = await w.upload(opts); + return { + statusCode: response.$ResponseMetadata.statusCode, + requestId: response.$ResponseMetadata.requestId, + headers: response.$ResponseMetadata.headers, + }; + }, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + tags: "test_tag1,test_tag2", + customCoordinates: "10, 10, 100, 100", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + isPrivateFile: true, + extensions, + }); + expect(meta.statusCode).toBe(200); + expect(meta.requestId).toBe("sdfsdfsdfdsf"); + expect(meta.headers).toMatchObject({ + "content-type": "application/json", + "x-request-id": "sdfsdfsdfdsf", + }); + }); + + test("Undefined fields should not be sent", async ({ page }) => { + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + tags: undefined, + folder: undefined, + isPrivateFile: undefined, + customCoordinates: undefined, + responseFields: undefined, + extensions: undefined, + webhookUrl: undefined, + overwriteFile: undefined, + overwriteAITags: undefined, + overwriteTags: undefined, + overwriteCustomMetadata: undefined, + customMetadata: undefined, + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.extensions).toBeUndefined(); + expect(f.tags).toBeUndefined(); + expect(f.folder).toBeUndefined(); + expect(f.isPrivateFile).toBeUndefined(); + expect(f.customCoordinates).toBeUndefined(); + expect(f.responseFields).toBeUndefined(); + expect(f.webhookUrl).toBeUndefined(); + expect(f.overwriteFile).toBeUndefined(); + expect(f.overwriteAITags).toBeUndefined(); + expect(f.overwriteTags).toBeUndefined(); + expect(f.overwriteCustomMetadata).toBeUndefined(); + expect(f.customMetadata).toBeUndefined(); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("With pre and post transformation", async ({ page }) => { + const transformation = { + pre: "w-100", + post: [{ type: "transformation", value: "w-100" }], + }; + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + transformation, + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.responseFields).toBe("tags, customCoordinates, isPrivateFile, metadata"); + expect(f.useUniqueFileName).toBe("false"); + expect(f.publicKey).toBe("test_public_key"); + expect(f.transformation).toBe(JSON.stringify(transformation)); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("With pre transformation", async ({ page }) => { + const transformation = { pre: "w-100" }; + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + transformation, + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.responseFields).toBe("tags, customCoordinates, isPrivateFile, metadata"); + expect(f.useUniqueFileName).toBe("false"); + expect(f.publicKey).toBe("test_public_key"); + expect(f.transformation).toBe(JSON.stringify(transformation)); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("With post transformation", async ({ page }) => { + const transformation = { post: [{ type: "transformation", value: "w-100" }] }; + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + transformation, + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.responseFields).toBe("tags, customCoordinates, isPrivateFile, metadata"); + expect(f.useUniqueFileName).toBe("false"); + expect(f.publicKey).toBe("test_public_key"); + expect(f.transformation).toBe(JSON.stringify(transformation)); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("Server 5xx without message", async ({ page }) => { + await mockUpload(page, { status: 500, body: JSON.stringify({ help: "" }) }); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isServer).toBe(true); + expect(result.error.message).toBe( + "Server error occurred while uploading the file. This is rare and usually temporary.", + ); + }); + + test("Should return error for an invalid pre transformation", async ({ page }) => { + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + transformation: { pre: "" }, + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isInvalid).toBe(true); + expect(result.error.message).toBe("Invalid pre transformation parameter."); + }); + + test("Should return error for an invalid post transformation of type abs", async ({ page }) => { + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + transformation: { post: [{ type: "abs", value: "" }] }, + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isInvalid).toBe(true); + expect(result.error.message).toBe("Invalid post transformation parameter."); + }); + + test("Should return error for an invalid post transformation of type transformation", async ({ page }) => { + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + transformation: { post: [{ type: "transformation", value: "" }] }, + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isInvalid).toBe(true); + expect(result.error.message).toBe("Invalid post transformation parameter."); + }); + + test("Should return error for an invalid post transformation if it's not an array", async ({ page }) => { + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + transformation: { post: {} }, + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isInvalid).toBe(true); + expect(result.error.message).toBe("Invalid post transformation parameter."); + }); + + test("With checks option", async ({ page }) => { + const mock = await mockUpload(page); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + responseFields: "tags, customCoordinates, isPrivateFile, metadata", + useUniqueFileName: false, + checks: "'request.folder' : '/'", + }); + expect(result.ok).toBe(true); + if (!result.ok) return; + + const f = mock.fields(); + expect(f.file).toBe("test_file"); + expect(f.fileName).toBe("test_file_name"); + expect(f.responseFields).toBe("tags, customCoordinates, isPrivateFile, metadata"); + expect(f.useUniqueFileName).toBe("false"); + expect(f.publicKey).toBe("test_public_key"); + expect(f.checks).toBe("'request.folder' : '/'"); + expect(result.response).toEqual(uploadSuccessResponseObj); + }); + + test("onProgress callback is triggered during upload", async ({ page }) => { + await mockUpload(page); + const out = await page.evaluate(async (opts) => { + const w = window as any; + const xhr = new XMLHttpRequest(); + let calls = 0; + const promise = w.upload({ ...opts, xhr, onProgress: () => { calls++; } }); + // The SDK wires xhr.upload.onprogress synchronously before sending, so a + // dispatched progress event must be forwarded to the callback. + xhr.upload.dispatchEvent( + new ProgressEvent("progress", { lengthComputable: true, loaded: 50, total: 100 }), + ); + const response = await promise; + return { calls, response }; + }, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + }); + expect(out.calls).toBeGreaterThanOrEqual(1); + expect(out.response).toEqual(uploadSuccessResponseObj); + }); + + test("Abort signal aborts the upload", async ({ page }) => { + await mockUpload(page, { hang: true }); + const out = await page.evaluate(async (opts) => { + const w = window as any; + const controller = new AbortController(); + const promise = w.upload({ ...opts, abortSignal: controller.signal }); + controller.abort(); + try { + await promise; + return { ok: true as const }; + } catch (e: any) { + return { + ok: false as const, + isAbort: e instanceof w.ImageKitAbortError, + reasonName: e?.reason?.name, + }; + } + }, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + }); + expect(out.ok).toBe(false); + if (out.ok) return; + expect(out.isAbort).toBe(true); + expect(out.reasonName).toBe("AbortError"); + }); + + test("Abort signal aborts the upload with reason", async ({ page }) => { + await mockUpload(page, { hang: true }); + const out = await page.evaluate(async (opts) => { + const w = window as any; + const controller = new AbortController(); + const promise = w.upload({ ...opts, abortSignal: controller.signal }); + controller.abort("abort reason"); + try { + await promise; + return { ok: true as const }; + } catch (e: any) { + return { + ok: false as const, + isAbort: e instanceof w.ImageKitAbortError, + reason: e?.reason, + }; + } + }, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + }); + expect(out.ok).toBe(false); + if (out.ok) return; + expect(out.isAbort).toBe(true); + expect(out.reason).toBe("abort reason"); + }); + + test("Already aborted signal should abort upload immediately", async ({ page }) => { + const out = await page.evaluate(async (opts) => { + const w = window as any; + const controller = new AbortController(); + controller.abort(); + try { + await w.upload({ ...opts, abortSignal: controller.signal }); + return { ok: true as const }; + } catch (e: any) { + return { + ok: false as const, + isAbort: e instanceof w.ImageKitAbortError, + reasonName: e?.reason?.name, + }; + } + }, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + }); + expect(out.ok).toBe(false); + if (out.ok) return; + expect(out.isAbort).toBe(true); + expect(out.reasonName).toBe("AbortError"); + }); + + test("Error during upload 4xx with invalid JSON response", async ({ page }) => { + await mockUpload(page, { status: 400, body: "sdf" }); + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isSyntax).toBe(true); + }); + + test("Should return error for an invalid transformation object in upload", async ({ page }) => { + const result = await runUpload(page, { + ...securityParameters, + fileName: "test_file_name", + file: "test_file", + transformation: 123, + }); + expect(result.ok).toBe(false); + if (result.ok) return; + expect(result.error.isInvalid).toBe(true); + expect(result.error.message).toBe( + "Invalid transformation parameter. Please include at least pre, post, or both.", + ); + }); +}); diff --git a/test/data/index.js b/test/data/index.js deleted file mode 100644 index 5e0ede3..0000000 --- a/test/data/index.js +++ /dev/null @@ -1,5 +0,0 @@ -module.exports.initializationParams = { - publicKey: "test_public_key", - urlEndpoint: "https://ik.imagekit.io/test_url_endpoint", - authenticationEndpoint: "http://test/auth" -} \ No newline at end of file diff --git a/test/initialization.js b/test/initialization.js deleted file mode 100644 index 8f87592..0000000 --- a/test/initialization.js +++ /dev/null @@ -1,71 +0,0 @@ -const chai = require("chai"); -const expect = chai.expect; -const initializationParams = require("./data").initializationParams -import ImageKit from "../src/index"; - - -describe("Initialization checks", function () { - var imagekit = new ImageKit(initializationParams); - - it('should throw error: options - empty object', function () { - try { - new ImageKit({}); - } catch(err) { - expect(err.message).to.be.equal('Missing urlEndpoint during SDK initialization'); - } - }); - - it('should throw error: options - undefined', function () { - try { - new ImageKit(); - } catch(err) { - expect(err.message).to.be.equal('Missing urlEndpoint during SDK initialization'); - } - }); - - it('Pass private Key', function () { - try { - new ImageKit({ - urlEndpoint: initializationParams.urlEndpoint, - privateKey: "should_not_pass" - }); - } catch(err) { - expect(err.message).to.be.equal('privateKey should not be passed on the client side'); - } - }); - - it('should have options object', function () { - expect(imagekit.options).to.be.an('object'); - }); - - it('should have correctly initialized options object.', function () { - expect(imagekit.options).to.have.property('publicKey').to.be.equal(initializationParams.publicKey); - expect(imagekit.options).to.have.property('urlEndpoint').to.be.equal(initializationParams.urlEndpoint); - expect(imagekit.options).to.have.property('authenticationEndpoint').to.be.equal(initializationParams.authenticationEndpoint); - }); - - it("should have callable functions 'url' and 'upload'", function () { - expect(imagekit.url).to.exist.and.to.be.a('function'); - expect(imagekit.upload).to.exist.and.to.be.a('function'); - }); - - it('only urlEndpoint is required parameter', function () { - let imagekit = new ImageKit({ - urlEndpoint: initializationParams.urlEndpoint - }); - - expect(imagekit.options).to.be.an('object'); - expect(imagekit.options).to.have.property('urlEndpoint').to.be.equal(initializationParams.urlEndpoint); - expect(imagekit.url).to.exist.and.to.be.a('function'); - expect(imagekit.upload).to.exist.and.to.be.a('function'); - - }); - - it('should throw error: invalid transformationPosition', function () { - try { - new ImageKit({...initializationParams, transformationPosition: "test"}); - } catch(err) { - expect(err.message).to.be.equal('Invalid transformationPosition parameter'); - } - }); -}); \ No newline at end of file diff --git a/test/upload.js b/test/upload.js deleted file mode 100644 index 24cded2..0000000 --- a/test/upload.js +++ /dev/null @@ -1,1181 +0,0 @@ -const chai = require("chai"); -const sinon = require("sinon"); -global.FormData = require("formdata-node"); -global.Blob = require("web-file-polyfill").Blob -global.File = require("web-file-polyfill").File -const expect = chai.expect; -const initializationParams = require("./data").initializationParams -import ImageKit from "../src/index"; -var requests, server; -import 'regenerator-runtime/runtime' - -const uploadSuccessResponseObj = { - "fileId": "598821f949c0a938d57563bd", - "name": "file1.jpg", - "url": "https://ik.imagekit.io/your_imagekit_id/images/products/file1.jpg", - "thumbnailUrl": "https://ik.imagekit.io/your_imagekit_id/tr:n-media_library_thumbnail/images/products/file1.jpg", - "height": 300, - "width": 200, - "size": 83622, - "filePath": "/images/products/file1.jpg", - "tags": ["t-shirt", "round-neck", "sale2019"], - "isPrivateFile": false, - "customCoordinates": null, - "fileType": "image", - "AITags": [{ "name": "Face", "confidence": 99.95, "source": "aws-auto-tagging" }], - "extensionStatus": { "aws-auto-tagging": "success" } -}; - -function successSignature() { - server.respondWith("GET", new RegExp(initializationParams.authenticationEndpoint + ".*"), - [ - 200, - { "Content-Type": "application/json" }, - JSON.stringify({ - signature: "test_signature", - expire: 123, - token: "test_token" - }) - ]); - server.respond(); -} - -function nonSuccessErrorSignature() { - server.respondWith("GET", new RegExp(initializationParams.authenticationEndpoint + ".*"), - [ - 403, - { "Content-Type": "application/json" }, - JSON.stringify({ - error: "Not allowed" - }) - ]); - server.respond(); -} - -function successUploadResponse() { - server.respondWith("POST", "https://upload.imagekit.io/api/v1/files/upload", - [ - 200, - { "Content-Type": "application/json" }, - JSON.stringify(uploadSuccessResponseObj) - ] - ); - server.respond(); -} - -function errorUploadResponse(statusCode, obj) { - obj = obj || { - "message": "Your account cannot be authenticated.", - "help": "For support kindly contact us at support@imagekit.io ." - }; - server.respondWith("POST", "https://upload.imagekit.io/api/v1/files/upload", - [ - statusCode || 400, - { "Content-Type": "application/json" }, - JSON.stringify(obj) - ] - ); - server.respond(); -} - -async function sleep(ms = 0) { - return new Promise((resolve, reject) => { - setTimeout(() => { - resolve(); - }, ms); - }); -} - -describe("File upload", function () { - - var imagekit = new ImageKit(initializationParams); - - beforeEach(() => { - global.XMLHttpRequest = sinon.useFakeXMLHttpRequest(); - requests = []; - global.XMLHttpRequest.onCreate = function (req) { requests.push(req); }; - server = sinon.createFakeServer(); - }); - - afterEach(() => { - // Like before we must clean up when tampering with globals. - global.XMLHttpRequest.restore(); - server.restore(); - }); - - it('Invalid options', function () { - var callback = sinon.spy(); - - imagekit.upload(undefined, callback); - expect(server.requests.length).to.be.equal(0); - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, { help: "", message: "Invalid uploadOptions parameter" }, null); - }); - - it('Missing fileName', function () { - const fileOptions = { - file: "https://ik.imagekit.io/remote-url.jpg" - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - expect(server.requests.length).to.be.equal(1); - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, { help: "", message: "Missing fileName parameter for upload" }, null); - }); - - it('Missing file', function () { - const fileOptions = { - fileName: "test_file_name", - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - expect(server.requests.length).to.be.equal(1); - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, { help: "", message: "Missing file parameter for upload" }, null); - }); - - it('Missing authEndpoint', function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file" - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback, { - authenticationEndpoint: "" - }); - - expect(server.requests.length).to.be.equal(1); - sinon.assert.calledWith(callback, { message: "Missing authentication endpoint for upload", help: "" }, null); - }); - - it('Missing public key', function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file" - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback, { - publicKey: "" - }); - - expect(server.requests.length).to.be.equal(1); - sinon.assert.calledWith(callback, { message: "Missing public key for upload", help: "" }, null); - }); - - it('Auth endpoint network error handling', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file" - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback, { - authenticationEndpoint: "https://does-not-exist-sdfsdf/aut" - }); - - expect(server.requests.length).to.be.equal(2); - - // Simulate network error on authentication endpoint - server.requests[1].error(); - await sleep(); - sinon.assert.calledWith(callback, { message: "Request to authenticationEndpoint failed due to network error", help: "" }, null); - }); - - it('Auth endpoint non 200 status code handling', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file" - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - - // Simulate non 200 response on authentication endpoint - nonSuccessErrorSignature(); - await sleep(); - sinon.assert.calledWith(callback, { message: "Invalid response from authenticationEndpoint. The SDK expects a JSON response with three fields i.e. signature, token and expire.", help: "" }, null); - }); - - it('Auth endpoint 200 status with bad body', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file" - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - - // Simulate non 200 response on authentication endpoint - server.respondWith("GET", new RegExp(initializationParams.authenticationEndpoint + ".*"), - [ - 200, - { "Content-Type": "application/json" }, - "invalid json" - ]); - server.respond(); - await sleep(); - sinon.assert.calledWith(callback, { message: "Invalid response from authenticationEndpoint. The SDK expects a JSON response with three fields i.e. signature, token and expire.", help: "" }, null); - }); - - it('Auth endpoint 200 status missing token', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file" - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - - // Simulate non 200 response on authentication endpoint - server.respondWith("GET", new RegExp(initializationParams.authenticationEndpoint + ".*"), - [ - 200, - { "Content-Type": "application/json" }, - JSON.stringify({ - signature: "sig", - timestamp: "123" - }) - ]); - server.respond(); - await sleep(); - sinon.assert.calledWith(callback, { message: "Invalid response from authenticationEndpoint. The SDK expects a JSON response with three fields i.e. signature, token and expire.", help: "" }, null); - }); - - it('Upload endpoint network error handling', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file" - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - successSignature(); - await sleep(); - - // Simulate network error on upload API - server.requests[0].error(); - await sleep(); - sinon.assert.calledWith(callback, { message: "Request to ImageKit upload endpoint failed due to network error", help: "" }, null); - }); - - it('Boolean handling', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file", - tags: "test_tag1,test_tag2", - customCoordinates: "10, 10, 100, 100", - responseFields: "tags, customCoordinates, isPrivateFile, metadata", - useUniqueFileName: false, - isPrivateFile: true - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - successSignature(); - await sleep(); - successUploadResponse(); - await sleep(); - - var arg = server.requests[0].requestBody; - expect(arg.get('file')).to.be.equal("test_file"); - expect(arg.get('fileName')).to.be.equal("test_file_name"); - expect(arg.get('token')).to.be.equal("test_token"); - expect(arg.get('expire')).to.be.equal("123"); - expect(arg.get('signature')).to.be.equal("test_signature"); - expect(arg.get('tags')).to.be.equal("test_tag1,test_tag2"); - expect(arg.get('customCoordinates')).to.be.equal("10, 10, 100, 100"); - expect(arg.get('responseFields')).to.be.equal("tags, customCoordinates, isPrivateFile, metadata"); - expect(arg.get('useUniqueFileName')).to.be.equal('false'); - expect(arg.get('isPrivateFile')).to.be.equal('true'); - expect(arg.get('publicKey')).to.be.equal('test_public_key'); - - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, null, uploadSuccessResponseObj); - }); - - it('Tag array handling', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file", - tags: ["test_tag1", "test_tag2"], - useUniqueFileName: false, - isPrivateFile: true - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - successSignature(); - await sleep(); - successUploadResponse(); - await sleep(); - - var arg = server.requests[0].requestBody; - expect(arg.get('file')).to.be.equal("test_file"); - expect(arg.get('fileName')).to.be.equal("test_file_name"); - expect(arg.get('token')).to.be.equal("test_token"); - expect(arg.get('expire')).to.be.equal("123"); - expect(arg.get('signature')).to.be.equal("test_signature"); - expect(arg.get('tags')).to.be.equal("test_tag1,test_tag2"); - expect(arg.get('useUniqueFileName')).to.be.equal('false'); - expect(arg.get('isPrivateFile')).to.be.equal('true'); - expect(arg.get('publicKey')).to.be.equal('test_public_key'); - - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, null, uploadSuccessResponseObj); - }); - - it('Missing useUniqueFileName', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file", - tags: ["test_tag1", "test_tag2"], - isPrivateFile: true - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - successSignature(); - await sleep(); - successUploadResponse(); - await sleep(); - - var arg = server.requests[0].requestBody; - expect(arg.get('file')).to.be.equal("test_file"); - expect(arg.get('fileName')).to.be.equal("test_file_name"); - expect(arg.get('token')).to.be.equal("test_token"); - expect(arg.get('expire')).to.be.equal("123"); - expect(arg.get('signature')).to.be.equal("test_signature"); - expect(arg.get('tags')).to.be.equal("test_tag1,test_tag2"); - expect(arg.get('isPrivateFile')).to.be.equal('true'); - expect(arg.get('publicKey')).to.be.equal('test_public_key'); - expect(arg.get('useUniqueFileName')).to.be.equal(undefined); - expect(arg.get('customCoordinates')).to.be.equal(undefined); - expect(arg.get('responseFields')).to.be.equal(undefined); - - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, null, uploadSuccessResponseObj); - }); - - it('Missing isPrivateFile', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file", - tags: ["test_tag1", "test_tag2"] - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - successSignature(); - await sleep(); - successUploadResponse(); - await sleep(); - - var arg = server.requests[0].requestBody; - expect(arg.get('file')).to.be.equal("test_file"); - expect(arg.get('fileName')).to.be.equal("test_file_name"); - expect(arg.get('token')).to.be.equal("test_token"); - expect(arg.get('expire')).to.be.equal("123"); - expect(arg.get('signature')).to.be.equal("test_signature"); - expect(arg.get('tags')).to.be.equal("test_tag1,test_tag2"); - expect(arg.get('publicKey')).to.be.equal('test_public_key'); - expect(arg.get('isPrivateFile')).to.be.equal(undefined); - expect(arg.get('useUniqueFileName')).to.be.equal(undefined); - expect(arg.get('customCoordinates')).to.be.equal(undefined); - expect(arg.get('responseFields')).to.be.equal(undefined); - - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, null, uploadSuccessResponseObj); - }); - - it('With extensions parameter', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file", - tags: "test_tag1,test_tag2", - customCoordinates: "10, 10, 100, 100", - responseFields: "tags, customCoordinates, isPrivateFile, metadata", - useUniqueFileName: false, - isPrivateFile: true, - extensions: [ - { - name: "aws-auto-tagging", - minConfidence: 80, - maxTags: 10 - } - ], - webhookUrl: "https://your-domain/?appId=some-id" - }; - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - successSignature(); - await sleep(); - successUploadResponse(); - await sleep(); - - var arg = server.requests[0].requestBody; - - expect(arg.get('file')).to.be.equal("test_file"); - expect(arg.get('fileName')).to.be.equal("test_file_name"); - expect(arg.get('token')).to.be.equal("test_token"); - expect(arg.get('expire')).to.be.equal("123"); - expect(arg.get('signature')).to.be.equal("test_signature"); - expect(arg.get('tags')).to.be.equal("test_tag1,test_tag2"); - expect(arg.get('customCoordinates')).to.be.equal("10, 10, 100, 100"); - expect(arg.get('responseFields')).to.be.equal("tags, customCoordinates, isPrivateFile, metadata"); - expect(arg.get('useUniqueFileName')).to.be.equal('false'); - expect(arg.get('isPrivateFile')).to.be.equal('true'); - expect(arg.get('publicKey')).to.be.equal('test_public_key'); - expect(arg.get('extensions')).to.be.equal(JSON.stringify(fileOptions.extensions)); - expect(arg.get('webhookUrl')).to.be.equal('https://your-domain/?appId=some-id') - - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, null, uploadSuccessResponseObj); - }); - - it('Bare minimum request', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file", - tags: undefined - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - successSignature(); - await sleep(); - successUploadResponse(); - await sleep(); - - var arg = server.requests[0].requestBody; - expect(arg.get('file')).to.be.equal("test_file"); - expect(arg.get('fileName')).to.be.equal("test_file_name"); - expect(arg.get('token')).to.be.equal("test_token"); - expect(arg.get('expire')).to.be.equal("123"); - expect(arg.get('signature')).to.be.equal("test_signature"); - expect(arg.get('publicKey')).to.be.equal('test_public_key'); - expect(arg.get('tags')).to.be.equal(undefined); - expect(arg.get('isPrivateFile')).to.be.equal(undefined); - expect(arg.get('useUniqueFileName')).to.be.equal(undefined); - expect(arg.get('customCoordinates')).to.be.equal(undefined); - expect(arg.get('responseFields')).to.be.equal(undefined); - - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, null, uploadSuccessResponseObj); - }); - - it('Bare minimum request: Blob', async function () { - const buffer = Buffer.from("test_buffer") - const fileOptions = { - fileName: "test_file_name", - file: buffer - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - successSignature(); - await sleep(); - successUploadResponse(); - await sleep(); - - var arg = server.requests[0].requestBody; - - expect(arg.get('file').size).to.be.eq(buffer.length); - expect(arg.get('fileName')).to.be.equal("test_file_name"); - expect(arg.get('token')).to.be.equal("test_token"); - expect(arg.get('expire')).to.be.equal("123"); - expect(arg.get('signature')).to.be.equal("test_signature"); - expect(arg.get('publicKey')).to.be.equal('test_public_key'); - expect(arg.get('tags')).to.be.equal(undefined); - expect(arg.get('isPrivateFile')).to.be.equal(undefined); - expect(arg.get('useUniqueFileName')).to.be.equal(undefined); - expect(arg.get('customCoordinates')).to.be.equal(undefined); - expect(arg.get('responseFields')).to.be.equal(undefined); - - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, null, uploadSuccessResponseObj); - }); - - it('Error during upload', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file" - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - successSignature(); - await sleep(); - var errRes = { - help: "For support kindly contact us at support@imagekit.io .", - message: "Your account cannot be authenticated." - } - errorUploadResponse(500, errRes); - await sleep(); - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, errRes, null); - }); - - it('Error during upload non 2xx with bad body', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file" - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - successSignature(); - await sleep(); - server.respondWith("POST", "https://upload.imagekit.io/api/v1/files/upload", - [ - 500, - { "Content-Type": "application/json" }, - "sdf" - ] - ); - server.respond(); - await sleep(); - expect(callback.calledOnce).to.be.true; - var error = callback.args[0][0]; - expect(error instanceof SyntaxError).to.be.true; - }); - - it('Error during upload 2xx with bad body', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file" - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - successSignature(); - await sleep(); - server.respondWith("POST", "https://upload.imagekit.io/api/v1/files/upload", - [ - 200, - { "Content-Type": "application/json" }, - "sdf" - ] - ); - server.respond(); - await sleep(); - expect(callback.calledOnce).to.be.true; - var error = callback.args[0][0]; - expect(error instanceof SyntaxError).to.be.true; - }); - - it('Upload via URL', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "https://ik.imagekit.io/remote-url.jpg" - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - successSignature(); - await sleep(); - successUploadResponse(); - await sleep(); - - var arg = server.requests[0].requestBody; - expect(arg.get('file')).to.be.equal("https://ik.imagekit.io/remote-url.jpg"); - expect(arg.get('fileName')).to.be.equal("test_file_name"); - expect(arg.get('token')).to.be.equal("test_token"); - expect(arg.get('expire')).to.be.equal("123"); - expect(arg.get('signature')).to.be.equal("test_signature"); - expect(arg.get('publicKey')).to.be.equal('test_public_key'); - expect(arg.get('tags')).to.be.equal(undefined); - expect(arg.get('isPrivateFile')).to.be.equal(undefined); - expect(arg.get('useUniqueFileName')).to.be.equal(undefined); - expect(arg.get('customCoordinates')).to.be.equal(undefined); - expect(arg.get('responseFields')).to.be.equal(undefined); - - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, null, uploadSuccessResponseObj); - }); - - it('Overriding public key and authentication endpoint', async function () { - var newAuthEndpoint = "http://test/auth-override"; - var newPublicKey = "override_public_key"; - - const fileOptions = { - fileName: "test_file_name", - file: "https://ik.imagekit.io/remote-url.jpg" - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback, { - authenticationEndpoint: newAuthEndpoint, - publicKey: newPublicKey - }); - - expect(server.requests.length).to.be.equal(2); - server.respondWith("GET", new RegExp(newAuthEndpoint + ".*"), - [ - 200, - { "Content-Type": "application/json" }, - JSON.stringify({ - signature: "override_test_signature", - expire: 123123, - token: "override_test_token" - }) - ]); - server.respond(); - await sleep(); - successUploadResponse(); - await sleep(); - - var arg = server.requests[0].requestBody; - expect(arg.get('file')).to.be.equal("https://ik.imagekit.io/remote-url.jpg"); - expect(arg.get('fileName')).to.be.equal("test_file_name"); - expect(arg.get('token')).to.be.equal("override_test_token"); - expect(arg.get('expire')).to.be.equal("123123"); - expect(arg.get('signature')).to.be.equal("override_test_signature"); - expect(arg.get('publicKey')).to.be.equal('override_public_key'); - expect(arg.get('tags')).to.be.equal(undefined); - expect(arg.get('isPrivateFile')).to.be.equal(undefined); - expect(arg.get('useUniqueFileName')).to.be.equal(undefined); - expect(arg.get('customCoordinates')).to.be.equal(undefined); - expect(arg.get('responseFields')).to.be.equal(undefined); - expect(arg.get('extensions')).to.be.equal(undefined); - expect(arg.get('customMetadata')).to.be.equal(undefined); - - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, null, uploadSuccessResponseObj); - }); - - it('With overwrite parameters', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file", - tags: "test_tag1,test_tag2", - customCoordinates: "10, 10, 100, 100", - responseFields: "tags, customCoordinates, isPrivateFile, metadata", - useUniqueFileName: false, - isPrivateFile: true, - extensions: [ - { - name: "aws-auto-tagging", - minConfidence: 80, - maxTags: 10 - } - ], - overwriteFile: false, - overwriteAITags: false, - overwriteTags: false, - overwriteCustomMetadata: false - }; - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - successSignature(); - await sleep(); - successUploadResponse(); - await sleep(); - - var arg = server.requests[0].requestBody; - - expect(arg.get('file')).to.be.equal("test_file"); - expect(arg.get('fileName')).to.be.equal("test_file_name"); - expect(arg.get('token')).to.be.equal("test_token"); - expect(arg.get('expire')).to.be.equal("123"); - expect(arg.get('signature')).to.be.equal("test_signature"); - expect(arg.get('tags')).to.be.equal("test_tag1,test_tag2"); - expect(arg.get('customCoordinates')).to.be.equal("10, 10, 100, 100"); - expect(arg.get('responseFields')).to.be.equal("tags, customCoordinates, isPrivateFile, metadata"); - expect(arg.get('useUniqueFileName')).to.be.equal('false'); - expect(arg.get('isPrivateFile')).to.be.equal('true'); - expect(arg.get('publicKey')).to.be.equal('test_public_key'); - expect(arg.get('extensions')).to.be.equal(JSON.stringify(fileOptions.extensions)); - expect(arg.get('overwriteFile')).to.be.equal('false'); - expect(arg.get('overwriteAITags')).to.be.equal('false'); - expect(arg.get('overwriteTags')).to.be.equal('false'); - expect(arg.get('overwriteCustomMetadata')).to.be.equal('false'); - - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, null, uploadSuccessResponseObj); - }); - - it('With customMetadata', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file", - tags: "test_tag1,test_tag2", - customCoordinates: "10, 10, 100, 100", - responseFields: "tags, customCoordinates, isPrivateFile, metadata", - useUniqueFileName: false, - isPrivateFile: true, - extensions: [ - { - name: "aws-auto-tagging", - minConfidence: 80, - maxTags: 10 - } - ], - overwriteFile: false, - overwriteAITags: false, - overwriteTags: false, - overwriteCustomMetadata: false, - customMetadata: { - brand: "Nike", - color: "red" - }, - }; - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - successSignature(); - await sleep(); - successUploadResponse(); - await sleep(); - - var arg = server.requests[0].requestBody; - - expect(arg.get('file')).to.be.equal("test_file"); - expect(arg.get('fileName')).to.be.equal("test_file_name"); - expect(arg.get('token')).to.be.equal("test_token"); - expect(arg.get('expire')).to.be.equal("123"); - expect(arg.get('signature')).to.be.equal("test_signature"); - expect(arg.get('tags')).to.be.equal("test_tag1,test_tag2"); - expect(arg.get('customCoordinates')).to.be.equal("10, 10, 100, 100"); - expect(arg.get('responseFields')).to.be.equal("tags, customCoordinates, isPrivateFile, metadata"); - expect(arg.get('useUniqueFileName')).to.be.equal('false'); - expect(arg.get('isPrivateFile')).to.be.equal('true'); - expect(arg.get('publicKey')).to.be.equal('test_public_key'); - expect(arg.get('extensions')).to.be.equal(JSON.stringify(fileOptions.extensions)); - expect(arg.get('overwriteFile')).to.be.equal('false'); - expect(arg.get('overwriteAITags')).to.be.equal('false'); - expect(arg.get('overwriteTags')).to.be.equal('false'); - expect(arg.get('overwriteCustomMetadata')).to.be.equal('false'); - expect(arg.get('customMetadata')).to.be.equal(JSON.stringify(fileOptions.customMetadata)); - - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, null, uploadSuccessResponseObj); - }); - - it('Array type fields', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file", - tags: ["test_tag1", "test_tag2"], - customCoordinates: "10, 10, 100, 100", - responseFields: ["tags", "customCoordinates", "isPrivateFile", "metadata"], - useUniqueFileName: false, - isPrivateFile: true, - extensions: [ - { - name: "aws-auto-tagging", - minConfidence: 80, - maxTags: 10 - } - ], - overwriteFile: false, - overwriteAITags: false, - overwriteTags: false, - overwriteCustomMetadata: false, - customMetadata: { - brand: "Nike", - color: "red" - }, - }; - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - successSignature(); - await sleep(); - successUploadResponse(); - await sleep(); - - var arg = server.requests[0].requestBody; - - expect(arg.get('file')).to.be.equal("test_file"); - expect(arg.get('fileName')).to.be.equal("test_file_name"); - expect(arg.get('token')).to.be.equal("test_token"); - expect(arg.get('expire')).to.be.equal("123"); - expect(arg.get('signature')).to.be.equal("test_signature"); - expect(arg.get('tags')).to.be.equal("test_tag1,test_tag2"); - expect(arg.get('customCoordinates')).to.be.equal("10, 10, 100, 100"); - expect(arg.get('responseFields')).to.be.equal("tags,customCoordinates,isPrivateFile,metadata"); - expect(arg.get('useUniqueFileName')).to.be.equal('false'); - expect(arg.get('isPrivateFile')).to.be.equal('true'); - expect(arg.get('publicKey')).to.be.equal('test_public_key'); - expect(arg.get('extensions')).to.be.equal(JSON.stringify(fileOptions.extensions)); - expect(arg.get('overwriteFile')).to.be.equal('false'); - expect(arg.get('overwriteAITags')).to.be.equal('false'); - expect(arg.get('overwriteTags')).to.be.equal('false'); - expect(arg.get('overwriteCustomMetadata')).to.be.equal('false'); - expect(arg.get('customMetadata')).to.be.equal(JSON.stringify(fileOptions.customMetadata)); - - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, null, uploadSuccessResponseObj); - }); - - it('check custom XHR object is used', async function () { - var xhr = new XMLHttpRequest(); - var fun = function () { return "hello from function" }; - xhr.onprogress = fun; - const fileOptions = { - fileName: "test_file_name", - file: "test_file", - tags: "test_tag1,test_tag2", - customCoordinates: "10, 10, 100, 100", - responseFields: "tags, customCoordinates, isPrivateFile, metadata", - useUniqueFileName: false, - isPrivateFile: true, - extensions: [ - { - name: "aws-auto-tagging", - minConfidence: 80, - maxTags: 10 - } - ], - xhr - }; - var callback = sinon.spy(); - imagekit.upload(fileOptions, callback); - expect(server.requests.length).to.be.equal(2); - expect(server.requests[0]).to.be.equal(xhr); - expect(server.requests[0].onprogress.toString()).to.be.equal(fun.toString()); - successSignature(); - await sleep(); - successUploadResponse(); - await sleep(); - - var arg = server.requests[0].requestBody; - - expect(arg.get('file')).to.be.equal("test_file"); - expect(arg.get('fileName')).to.be.equal("test_file_name"); - expect(arg.get('token')).to.be.equal("test_token"); - expect(arg.get('expire')).to.be.equal("123"); - expect(arg.get('signature')).to.be.equal("test_signature"); - expect(arg.get('tags')).to.be.equal("test_tag1,test_tag2"); - expect(arg.get('customCoordinates')).to.be.equal("10, 10, 100, 100"); - expect(arg.get('responseFields')).to.be.equal("tags, customCoordinates, isPrivateFile, metadata"); - expect(arg.get('useUniqueFileName')).to.be.equal('false'); - expect(arg.get('isPrivateFile')).to.be.equal('true'); - expect(arg.get('publicKey')).to.be.equal('test_public_key'); - expect(arg.get('extensions')).to.be.equal(JSON.stringify(fileOptions.extensions)); - - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, null, uploadSuccessResponseObj); - }); - - it('Upload using promise - success', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file", - tags: "test_tag1,test_tag2", - customCoordinates: "10, 10, 100, 100", - responseFields: "tags, customCoordinates, isPrivateFile, metadata", - useUniqueFileName: false, - isPrivateFile: true, - extensions: [ - { - name: "aws-auto-tagging", - minConfidence: 80, - maxTags: 10 - } - ] - }; - - var uploadPromise = imagekit.upload(fileOptions); - expect(server.requests.length).to.be.equal(2); - - successSignature(); - await sleep(); - successUploadResponse(); - await sleep(); - - var arg = server.requests[0].requestBody; - - expect(arg.get('file')).to.be.equal("test_file"); - expect(arg.get('fileName')).to.be.equal("test_file_name"); - expect(arg.get('token')).to.be.equal("test_token"); - expect(arg.get('expire')).to.be.equal("123"); - expect(arg.get('signature')).to.be.equal("test_signature"); - expect(arg.get('tags')).to.be.equal("test_tag1,test_tag2"); - expect(arg.get('customCoordinates')).to.be.equal("10, 10, 100, 100"); - expect(arg.get('responseFields')).to.be.equal("tags, customCoordinates, isPrivateFile, metadata"); - expect(arg.get('useUniqueFileName')).to.be.equal('false'); - expect(arg.get('isPrivateFile')).to.be.equal('true'); - expect(arg.get('publicKey')).to.be.equal('test_public_key'); - expect(arg.get('extensions')).to.be.equal(JSON.stringify(fileOptions.extensions)); - var response = await uploadPromise; - expect(response).to.be.deep.equal(uploadSuccessResponseObj); - }); - - it('Upload using promise - error', async function () { - var errRes = { - help: "For support kindly contact us at support@imagekit.io .", - message: "Your account cannot be authenticated." - } - const fileOptions = { - fileName: "test_file_name", - file: "test_file", - tags: "test_tag1,test_tag2", - customCoordinates: "10, 10, 100, 100", - responseFields: "tags, customCoordinates, isPrivateFile, metadata", - useUniqueFileName: false, - isPrivateFile: true, - extensions: [ - { - name: "aws-auto-tagging", - minConfidence: 80, - maxTags: 10 - } - ] - }; - - try { - var uploadPromise = imagekit.upload(fileOptions); - successSignature(); - await sleep(); - errorUploadResponse(500, errRes); - await sleep(); - var response = await uploadPromise; - } catch (ex) { - expect(ex).to.be.deep.equal(errRes); - } - }); - - it('Custom xhr promise', async function () { - var xhr = new XMLHttpRequest(); - var fun = function () { return "hello from function" }; - xhr.onprogress = fun; - const fileOptions = { - fileName: "test_file_name", - file: "test_file", - tags: "test_tag1,test_tag2", - customCoordinates: "10, 10, 100, 100", - responseFields: "tags, customCoordinates, isPrivateFile, metadata", - useUniqueFileName: false, - isPrivateFile: true, - extensions: [ - { - name: "aws-auto-tagging", - minConfidence: 80, - maxTags: 10 - } - ], - xhr - }; - var uploadPromise = imagekit.upload(fileOptions); - - expect(server.requests.length).to.be.equal(2); - - - successSignature(); - await sleep(); - successUploadResponse(); - await sleep(); - - var arg = server.requests[0].requestBody; - expect(arg.get('file')).to.be.equal("test_file"); - expect(server.requests[0]).to.be.equal(xhr); - expect(server.requests[0].onprogress.toString()).to.be.equal(fun.toString()); - - expect(arg.get('file')).to.be.equal("test_file"); - expect(arg.get('fileName')).to.be.equal("test_file_name"); - expect(arg.get('token')).to.be.equal("test_token"); - expect(arg.get('expire')).to.be.equal("123"); - expect(arg.get('signature')).to.be.equal("test_signature"); - expect(arg.get('tags')).to.be.equal("test_tag1,test_tag2"); - expect(arg.get('customCoordinates')).to.be.equal("10, 10, 100, 100"); - expect(arg.get('responseFields')).to.be.equal("tags, customCoordinates, isPrivateFile, metadata"); - expect(arg.get('useUniqueFileName')).to.be.equal('false'); - expect(arg.get('isPrivateFile')).to.be.equal('true'); - expect(arg.get('publicKey')).to.be.equal('test_public_key'); - expect(arg.get('extensions')).to.be.equal(JSON.stringify(fileOptions.extensions)); - - var response = await uploadPromise; - expect(response).to.be.deep.equal(uploadSuccessResponseObj); - }); - - it('$ResponseMetadata assertions using promise', async function () { - var dummyResonseHeaders = { - "Content-Type": "application/json", - "x-request-id": "sdfsdfsdfdsf" - }; - const fileOptions = { - fileName: "test_file_name", - file: "test_file", - tags: "test_tag1,test_tag2", - customCoordinates: "10, 10, 100, 100", - responseFields: "tags, customCoordinates, isPrivateFile, metadata", - useUniqueFileName: false, - isPrivateFile: true, - extensions: [ - { - name: "aws-auto-tagging", - minConfidence: 80, - maxTags: 10 - } - ] - }; - - var uploadPromise = imagekit.upload(fileOptions) - expect(server.requests.length).to.be.equal(2); - - successSignature(); - await sleep(); - - server.respondWith("POST", "https://upload.imagekit.io/api/v1/files/upload", - [ - 200, - dummyResonseHeaders, - JSON.stringify(uploadSuccessResponseObj) - ] - ); - server.respond(); - await sleep(); - - var response = await uploadPromise; - expect(response.$ResponseMetadata.headers).to.be.deep.equal(dummyResonseHeaders); - expect(response.$ResponseMetadata.statusCode).to.be.deep.equal(200); - }); - - it('$ResponseMetadata assertions using callback', async function () { - var dummyResonseHeaders = { - "Content-Type": "application/json", - "x-request-id": "sdfsdfsdfdsf" - }; - const fileOptions = { - fileName: "test_file_name", - file: "test_file" - }; - var callback = sinon.spy(); - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - - successSignature(); - await sleep(); - server.respondWith("POST", "https://upload.imagekit.io/api/v1/files/upload", - [ - 200, - dummyResonseHeaders, - JSON.stringify(uploadSuccessResponseObj) - ] - ); - server.respond(); - await sleep(); - - expect(callback.calledOnce).to.be.true; - - var callBackArguments = callback.args[0]; - expect(callBackArguments.length).to.be.eq(2); - var callbackResult = callBackArguments[1]; - - expect(callbackResult).to.be.deep.equal(uploadSuccessResponseObj); - expect(callbackResult.$ResponseMetadata.headers).to.be.deep.equal(dummyResonseHeaders); - expect(callbackResult.$ResponseMetadata.statusCode).to.be.deep.equal(200); - }); - - it('Undefined fields should not be sent', async function () { - const fileOptions = { - fileName: "test_file_name", - file: "test_file", - tags: undefined, - folder: undefined, - isPrivateFile: undefined, - customCoordinates: undefined, - responseFields: undefined, - extensions: undefined, - webhookUrl: undefined, - overwriteFile: undefined, - overwriteAITags: undefined, - overwriteTags: undefined, - overwriteCustomMetadata: undefined, - customMetadata: undefined - }; - - var callback = sinon.spy(); - - imagekit.upload(fileOptions, callback); - - expect(server.requests.length).to.be.equal(2); - successSignature(); - await sleep(); - successUploadResponse(); - await sleep(); - - var arg = server.requests[0].requestBody; - expect(arg.get('file')).to.be.equal("test_file"); - expect(arg.get('fileName')).to.be.equal("test_file_name"); - expect(arg.get('extensions')).to.be.equal(undefined); - expect(arg.get('tags')).to.be.equal(undefined); - expect(arg.get('folder')).to.be.equal(undefined); - expect(arg.get('isPrivateFile')).to.be.equal(undefined); - expect(arg.get('customCoordinates')).to.be.equal(undefined); - expect(arg.get('responseFields')).to.be.equal(undefined); - expect(arg.get('extensions')).to.be.equal(undefined); - expect(arg.get('webhookUrl')).to.be.equal(undefined); - expect(arg.get('overwriteFile')).to.be.equal(undefined); - expect(arg.get('overwriteAITags')).to.be.equal(undefined); - expect(arg.get('overwriteTags')).to.be.equal(undefined); - expect(arg.get('overwriteCustomMetadata')).to.be.equal(undefined); - expect(arg.get('customMetadata')).to.be.equal(undefined); - expect(callback.calledOnce).to.be.true; - sinon.assert.calledWith(callback, null, uploadSuccessResponseObj); - }); -}); diff --git a/test/url-generation.js b/test/url-generation.js deleted file mode 100644 index ae14851..0000000 --- a/test/url-generation.js +++ /dev/null @@ -1,348 +0,0 @@ -const chai = require("chai"); -const pkg = require("../package.json"); -global.FormData = require('formdata-node'); -const expect = chai.expect; -const initializationParams = require("./data").initializationParams -import ImageKit from "../src/index"; - -describe("URL generation", function () { - - var imagekit = new ImageKit(initializationParams); - - it('no path no src', function () { - const url = imagekit.url({}); - - expect(url).equal(""); - }); - - it('invalid src url', function () { - const url = imagekit.url({ src: "/" }); - - expect(url).equal(""); - }); - - it('no transformation path', function () { - const url = imagekit.url({ - path: "/test_path.jpg" - }); - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/test_path.jpg`); - }); - - it('no transformation src', function () { - const url = imagekit.url({ - src: "https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg" - }); - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg`); - }); - - it('Undefined parameters with path', function () { - const url = imagekit.url({ - path: "/test_path_alt.jpg", - transformation: undefined, - transformationPosition: undefined, - src: undefined, - }); - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg`); - }); - - it('should generate the url without sdk-version', function () { - const ik = new ImageKit({...initializationParams, sdkVersion: ""}) - - const url = ik.url({ - path: "/test_path.jpg", - transformation: [{ - "height": "300", - "width": "400" - }] - }); - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:h-300,w-400/test_path.jpg`); - }); - - it('should generate the correct url with path param', function () { - const url = imagekit.url({ - path: "/test_path.jpg", - transformation: [{ - "height": "300", - "width": "400" - }] - }); - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:h-300,w-400/test_path.jpg`); - }); - - it('should generate the correct url with path param with multiple leading slash', function () { - const url = imagekit.url({ - path: "///test_path.jpg", - transformation: [{ - "height": "300", - "width": "400" - }] - }) - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:h-300,w-400/test_path.jpg`); - - }); - - it('should generate the correct url with path param with overidden urlEndpoint', function () { - const url = imagekit.url({ - urlEndpoint: "https://ik.imagekit.io/test_url_endpoint_alt", - path: "/test_path.jpg", - transformation: [{ - "height": "300", - "width": "400" - }] - }) - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint_alt/tr:h-300,w-400/test_path.jpg`); - - }); - - it('should generate the correct url with path param with transformationPostion as query', function () { - const url = imagekit.url({ - path: "/test_path.jpg", - transformationPosition: "query", - transformation: [{ - "height": "300", - "width": "400" - }] - }); - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/test_path.jpg?tr=h-300%2Cw-400`); - }); - - it('should generate the correct url with src param', function () { - const url = imagekit.url({ - src: "https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg", - transformation: [{ - "height": "300", - "width": "400" - }] - }); - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg?tr=h-300%2Cw-400`); - }); - - it('should generate the correct url with transformationPostion as query', function () { - const url = imagekit.url({ - src: "https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg", - transformationPosition: "query", - transformation: [{ - "height": "300", - "width": "400" - }] - }); - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg?tr=h-300%2Cw-400`); - }); - - it('should generate the correct url with query params properly merged', function () { - const url = imagekit.url({ - src: "https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg?t1=v1", - queryParameters: { t2: "v2", t3: "v3" }, - transformation: [{ - "height": "300", - "width": "400" - }] - }); - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/test_path_alt.jpg?t1=v1&t2=v2&t3=v3&tr=h-300%2Cw-400`); - }); - - - it('should generate the correct chained transformation', function () { - const url = imagekit.url({ - path: "/test_path.jpg", - transformation: [{ - "height": "300", - "width": "400" - }, { - "rt": "90" - }] - }) - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:h-300,w-400:rt-90/test_path.jpg`); - }); - - - it('should generate the correct chained transformation url with new undocumented tranforamtion parameter', function () { - const url = imagekit.url({ - path: "/test_path.jpg", - transformation: [{ - "height": "300", - "width": "400" - }, { - "rndm_trnsf": "abcd" - }] - }) - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:h-300,w-400:rndm_trnsf-abcd/test_path.jpg`); - }); - - it('overlayImage', function () { - const url = imagekit.url({ - path: "/test_path.jpg", - transformation: [{ - "height": "300", - "width": "400", - overlayImage: "overlay.jpg" - }] - }) - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:h-300,w-400,oi-overlay.jpg/test_path.jpg`); - }); - - it('overlayImage with slash in path', function () { - const url = imagekit.url({ - path: "/test_path.jpg", - transformation: [{ - "height": "300", - "width": "400", - overlayImage: "/path/to/overlay.jpg" - }] - }) - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:h-300,w-400,oi-path@@to@@overlay.jpg/test_path.jpg`); - }); - - it('overlayX', function () { - const url = imagekit.url({ - path: "/test_path.jpg", - transformation: [{ - "height": "300", - "width": "400", - overlayX: 10 - }] - }) - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:h-300,w-400,ox-10/test_path.jpg`); - }); - - it('Border', function () { - const url = imagekit.url({ - path: "/test_path.jpg", - transformation: [{ - "height": "300", - "width": "400", - border: "20_FF0000" - }] - }) - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:h-300,w-400,b-20_FF0000/test_path.jpg`); - }); - - it('transformation with empty key and empty value', function () { - const url = imagekit.url({ - path: "/test_path.jpg", - transformation: [{ - "": "" - }] - }) - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:-/test_path.jpg`); - }); - - /** - * Provided to provide support to a new transform without sdk update - */ - it('transformation with undefined transform', function () { - const url = imagekit.url({ - path: "/test_path.jpg", - transformation: [{ - "undefined-transform": "true" - }] - }) - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:undefined-transform-true/test_path.jpg`); - }); - - it('transformation with empty value', function () { - const url = imagekit.url({ - path: "/test_path.jpg", - transformation: [{ - overlayImage: "" - }] - }) - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:oi-/test_path.jpg`); - }); - - it('transformation with - value', function () { - const url = imagekit.url({ - path: "/test_path.jpg", - transformation: [{ - effectContrast: "-" - }] - }) - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:e-contrast/test_path.jpg`); - }); - - it('All combined', function () { - const url = imagekit.url({ - path: "/test_path.jpg", - transformation: [{ - height: 300, - width: 400, - aspectRatio: '4-3', - quality: 40, - crop: 'force', - cropMode: 'extract', - focus: 'left', - format: 'jpeg', - radius: 50, - bg: "A94D34", - border: "5-A94D34", - rotation: 90, - blur: 10, - named: "some_name", - overlayX: 35, - overlayY: 35, - overlayFocus: "bottom", - overlayHeight: 20, - overlayWidth: 20, - overlayImage: "/folder/file.jpg", // leading slash case - overlayImageTrim: false, - overlayImageAspectRatio: "4:3", - overlayImageBackground: "0F0F0F", - overlayImageBorder: "10_0F0F0F", - overlayImageDPR: 2, - overlayImageQuality: 50, - overlayImageCropping: "force", - overlayText: "two words", - overlayTextFontSize: 20, - overlayTextFontFamily: "Open Sans", - overlayTextColor: "00FFFF", - overlayTextTransparency: 5, - overlayTextTypography: "b", - overlayBackground: "00AAFF55", - overlayTextEncoded: "b3ZlcmxheSBtYWRlIGVhc3k%3D", - overlayTextWidth: 50, - overlayTextBackground: "00AAFF55", - overlayTextPadding: 40, - overlayTextInnerAlignment: "left", - overlayRadius: 10, - progressive: true, - lossless: true, - trim: 5, - metadata: true, - colorProfile: true, - defaultImage: "folder/file.jpg/", //trailing slash case - dpr: 3, - effectSharpen: 10, - effectUSM: "2-2-0.8-0.024", - effectContrast: true, - effectGray: true, - original: true, - raw: "h-200,w-300,l-image,i-logo.png,l-end" - }] - }) - - expect(url).equal(`https://ik.imagekit.io/test_url_endpoint/tr:h-300,w-400,ar-4-3,q-40,c-force,cm-extract,fo-left,f-jpeg,r-50,bg-A94D34,b-5-A94D34,rt-90,bl-10,n-some_name,ox-35,oy-35,ofo-bottom,oh-20,ow-20,oi-folder@@file.jpg,oit-false,oiar-4:3,oibg-0F0F0F,oib-10_0F0F0F,oidpr-2,oiq-50,oic-force,ot-two%20words,ots-20,otf-Open%20Sans,otc-00FFFF,oa-5,ott-b,obg-00AAFF55,ote-b3ZlcmxheSBtYWRlIGVhc3k%3D,otw-50,otbg-00AAFF55,otp-40,otia-left,or-10,pr-true,lo-true,t-5,md-true,cp-true,di-folder@@file.jpg,dpr-3,e-sharpen-10,e-usm-2-2-0.8-0.024,e-contrast-true,e-grayscale-true,orig-true,h-200,w-300,l-image,i-logo.png,l-end/test_path.jpg`); - }); -}); - -