diff --git a/.github/actions/artifactory-oidc/action.yaml b/.github/actions/artifactory-oidc/action.yaml new file mode 100644 index 000000000..2cd0f16f6 --- /dev/null +++ b/.github/actions/artifactory-oidc/action.yaml @@ -0,0 +1,51 @@ +name: 'Artifactory OIDC Auth' +description: 'Exchange GitHub OIDC token for Artifactory access token and configure npm' + +runs: + using: 'composite' + steps: + - name: Exchange OIDC token for Artifactory access token + shell: bash + run: | + # 1. Request GitHub JWT with Artifactory as audience + GITHUB_JWT=$(curl -sS \ + -H "Authorization: bearer ${ACTIONS_ID_TOKEN_REQUEST_TOKEN}" \ + "${ACTIONS_ID_TOKEN_REQUEST_URL}&audience=${ARTIFACTORY_URL}" \ + | jq -r '.value') + + # Decode and log claims for debugging (payload is base64url, not secret) + PAYLOAD=$(echo "$GITHUB_JWT" | cut -d. -f2 | sed 's/-/+/g; s/_/\//g' | base64 -d 2>/dev/null || true) + echo "::debug::OIDC claims: sub=$(echo "$PAYLOAD" | jq -r '.sub'), aud=$(echo "$PAYLOAD" | jq -r '.aud')" + + # 2. Exchange GitHub JWT for Artifactory access token. + # Must be a JSON body and MUST include provider_name so JFrog knows + # which OIDC configuration to match (without it, no token is issued). + # Capture the full response so JFrog's error is visible on failure. + RESP=$(curl -sS "${ARTIFACTORY_URL}/access/api/v1/oidc/token" \ + -H 'Content-Type: application/json' \ + -d "{\"grant_type\":\"urn:ietf:params:oauth:grant-type:token-exchange\", + \"subject_token_type\":\"urn:ietf:params:oauth:token-type:id_token\", + \"subject_token\":\"${GITHUB_JWT}\", + \"provider_name\":\"github-actions\"}") + ART_TOKEN=$(echo "$RESP" | jq -r '.access_token // empty') + + if [ -z "$ART_TOKEN" ]; then + echo "::error::OIDC token exchange failed. Raw response (token field redacted):" + echo "$RESP" | jq 'if .access_token then .access_token="" else . end' 2>/dev/null || echo "$RESP" + exit 1 + fi + echo "::add-mask::$ART_TOKEN" + + # 3. Configure npm to use Artifactory registry + # always-auth: yarn 1 (bundled in twilio-cli, used by `twilio plugins:install` + # in the e2e tests) only sends the _authToken when always-auth is set; + # without it Artifactory returns 401 and yarn reports "Couldn't find package". + REGISTRY="${ARTIFACTORY_URL}/artifactory/api/npm/virtual-npm-thirdparty/" + HOST=$(echo "${ARTIFACTORY_URL}" | sed -E 's#^https?://##') + { + echo "registry=${REGISTRY}" + echo "//${HOST}/artifactory/api/npm/virtual-npm-thirdparty/:_authToken=${ART_TOKEN}" + echo "always-auth=true" + } > ~/.npmrc + + echo "::notice::npm configured to use Artifactory registry" \ No newline at end of file diff --git a/.github/scripts/lockfile-hygiene.sh b/.github/scripts/lockfile-hygiene.sh new file mode 100755 index 000000000..96cd137a8 --- /dev/null +++ b/.github/scripts/lockfile-hygiene.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# Lockfile & resolver-config hygiene gate (ADR 1634 Rule 3b). +# +# Public repos MUST stay resolvable by external consumers: a committed +# lockfile / resolver config that names a Twilio Artifactory host breaks any +# external `npm ci`. Twilio resolution is redirected at build time by config +# (the OIDC action writes ~/.npmrc), never in the repo — so the committed files +# must always point at the public registry. +# +# This script DETECTS violations and fails closed. It does not rewrite files; +# remediation is to regenerate the lockfile against the public registry. +set -euo pipefail + +# Known Twilio Artifactory hosts / aliases. Extend as new hosts appear. +PATTERNS='twilio\.jfrog\.io|artifactory\.twilio|artifacts\.twilio|\.artifactory\.twilioinfra|jfrog\.twilio' + +# Closed, enumerated detection surface (ADR Rule 3b). npmrc files and every +# committed lockfile / shrinkwrap. +# Portable (no mapfile): newline-delimited, iterated with a while-read loop. +FILES="$(git ls-files | grep -E '(^|/)(package-lock\.json|npm-shrinkwrap\.json|\.npmrc)$' || true)" + +if [ -z "$FILES" ]; then + echo "hygiene: no lockfiles or resolver configs tracked — nothing to check." + exit 0 +fi + +count="$(printf '%s\n' "$FILES" | grep -c .)" +echo "hygiene: scanning ${count} file(s) for Twilio Artifactory hosts..." +violations=0 +while IFS= read -r f; do + [ -n "$f" ] || continue + if hits=$(grep -nEi "$PATTERNS" "$f" 2>/dev/null); then + violations=1 + echo "::error file=$f::Artifactory host found in $f — public consumers cannot resolve this. Regenerate against the public registry." + echo " ── $f" + echo "$hits" | sed 's/^/ /' | head -8 + fi + # npm-shrinkwrap.json ships inside the published tarball — extra-loud. + case "$f" in + *npm-shrinkwrap.json) + echo "::warning file=$f::npm-shrinkwrap.json is published in the tarball; any Artifactory host here reaches consumers." ;; + esac +done </-/.tgz`) is +// identical on both, and `integrity` is left alone because Artifactory proxies +// byte-identical tarballs. A package published ONLY to Artifactory cannot be +// rewritten safely — it would 404 publicly — and this cannot detect that offline; +// the clean-room install in CI is what catches it. + +const { execFileSync } = require('child_process'); +const fs = require('fs'); + +const ARTIFACTORY = + /https:\/\/[^/"]*(?:twilio\.jfrog\.io|jfrog\.twilio|artifacts\.twilio|artifactory\.twilio)[^/"]*\/artifactory\/api\/npm\/[^/"]+\//g; +const PUBLIC = 'https://registry.npmjs.org/'; + +const staged = execFileSync('git', ['diff', '--cached', '--name-only', '--diff-filter=ACM'], { encoding: 'utf8' }) + .split('\n') + .filter((f) => /(^|\/)(package-lock\.json|npm-shrinkwrap\.json)$/.test(f)); + +if (!staged.length) process.exit(0); + +let rewrote = false; +for (const file of staged) { + const before = fs.readFileSync(file, 'utf8'); + const after = before.replace(ARTIFACTORY, PUBLIC); + if (before === after) continue; + const count = (before.match(ARTIFACTORY) || []).length; + fs.writeFileSync(file, after); + execFileSync('git', ['add', file]); + console.log(`lockfile: rewrote ${count} Artifactory URL(s) to the public registry in ${file}`); + rewrote = true; +} + +if (rewrote) { + console.log('lockfile: re-staged. CI still runs a clean-room public install to verify it resolves.'); +} diff --git a/.github/workflows/e2e.yml b/.github/workflows/e2e.yml index 23efa73bf..145af5c9b 100644 --- a/.github/workflows/e2e.yml +++ b/.github/workflows/e2e.yml @@ -6,6 +6,11 @@ name: E2E # freshly computed timestamp, so there was no way to point e2e at a particular # alpha. This takes the version as an input. # +# Runs the suite for every combination of webpack (4, 5) and Node (22, 24). +# max-parallel is 1 because each OS leg uses a single Twilio account, and two +# combinations against it at once would collide on plugins and releases. +# fail-fast is off so one failing combination does not hide the others. +# # Like publish.yml, this has to exist on the default branch for GitHub to expose # the workflow_dispatch trigger; a run can then target any branch. @@ -29,12 +34,21 @@ on: jobs: e2e-test: + name: e2e (webpack ${{ matrix.webpack }}, node ${{ matrix.node }}) + strategy: + fail-fast: false + max-parallel: 1 + matrix: + webpack: [4, 5] + node: ['22', '24'] uses: ./.github/workflows/~reusable_e2e_all_OS.yaml with: BRANCH: ${{ inputs.BRANCH }} NPM_IGNORE_PREFIX: ${{ vars.NPM_IGNORE_PREFIX }} PACKAGE_VERSION: ${{ inputs.PACKAGE_VERSION }} FLEX_UI_VERSION: ${{ inputs.FLEX_UI_VERSION }} + NODE_VERSION: ${{ matrix.node }} + WP5: ${{ matrix.webpack == 5 }} SEND_NOTIFICATION: false secrets: CONSOLE_EMAIL: ${{ secrets.CONSOLE_EMAIL }} diff --git a/.github/workflows/e2e_scheduled_wp5.yaml b/.github/workflows/e2e_scheduled_wp5.yaml new file mode 100644 index 000000000..0d2b998f0 --- /dev/null +++ b/.github/workflows/e2e_scheduled_wp5.yaml @@ -0,0 +1,91 @@ +name: Flex Plugins CLI - E2E Nightly - WebPack5 (Node 22) + +on: + schedule: + - cron: '15 4 * * *' # At 04:15 UTC (09:45 AM IST) + - cron: '15 5 * * *' # At 05:15 UTC (10:45 AM IST) + - cron: '15 6 * * *' # At 06:15 UTC (11:45 AM IST) + - cron: '15 7 * * *' # At 07:15 UTC (12:45 PM IST) + - cron: '15 8 * * *' # At 08:15 UTC (01:45 PM IST) + +jobs: + scheduled-e2e-wp5-unix: + if: github.event.schedule == '15 4 * * *' + uses: ./.github/workflows/~reusable_e2e_by_OS.yaml + with: + OS: ubuntu-latest-large + BRANCH: main + NPM_IGNORE_PREFIX: ${{ vars.NPM_IGNORE_PREFIX }} + NODE_VERSION: '22' + WP5: true + PACKAGE_VERSION: latest + FLEX_UI_VERSION: latest + SLACK_TITLE: 'Flex Plugins CLI - E2E Nightly - WebPack5' + SEND_NOTIFICATION: true + secrets: + CONSOLE_EMAIL: ${{ secrets.CONSOLE_EMAIL }} + CONSOLE_PASSWORD: ${{ secrets.CONSOLE_PASSWORD }} + CONSOLE_EMAIL_linux: ${{ secrets.CONSOLE_EMAIL_linux }} + TWILIO_ACCOUNT_SID_linux: ${{ secrets.TWILIO_ACCOUNT_SID_linux }} + TWILIO_AUTH_TOKEN_linux: ${{ secrets.TWILIO_AUTH_TOKEN_linux }} + CONSOLE_EMAIL_win32: ${{ secrets.CONSOLE_EMAIL_win32 }} + TWILIO_ACCOUNT_SID_win32: ${{ secrets.TWILIO_ACCOUNT_SID_win32 }} + TWILIO_AUTH_TOKEN_win32: ${{ secrets.TWILIO_AUTH_TOKEN_win32 }} + CONSOLE_EMAIL_darwin: ${{ secrets.CONSOLE_EMAIL_darwin }} + TWILIO_ACCOUNT_SID_darwin: ${{ secrets.TWILIO_ACCOUNT_SID_darwin }} + TWILIO_AUTH_TOKEN_darwin: ${{ secrets.TWILIO_AUTH_TOKEN_darwin }} + SLACK_WEB_HOOK: ${{ secrets.SLACK_WEB_HOOK }} + + scheduled-e2e-wp5-macos: + if: github.event.schedule == '15 6 * * *' + uses: ./.github/workflows/~reusable_e2e_by_OS.yaml + with: + OS: macos-latest + BRANCH: main + NPM_IGNORE_PREFIX: ${{ vars.NPM_IGNORE_PREFIX }} + NODE_VERSION: '22' + WP5: true + PACKAGE_VERSION: latest + FLEX_UI_VERSION: latest + SLACK_TITLE: 'Flex Plugins CLI - E2E Nightly - WebPack5' + SEND_NOTIFICATION: true + secrets: + CONSOLE_EMAIL: ${{ secrets.CONSOLE_EMAIL }} + CONSOLE_PASSWORD: ${{ secrets.CONSOLE_PASSWORD }} + CONSOLE_EMAIL_linux: ${{ secrets.CONSOLE_EMAIL_linux }} + TWILIO_ACCOUNT_SID_linux: ${{ secrets.TWILIO_ACCOUNT_SID_linux }} + TWILIO_AUTH_TOKEN_linux: ${{ secrets.TWILIO_AUTH_TOKEN_linux }} + CONSOLE_EMAIL_win32: ${{ secrets.CONSOLE_EMAIL_win32 }} + TWILIO_ACCOUNT_SID_win32: ${{ secrets.TWILIO_ACCOUNT_SID_win32 }} + TWILIO_AUTH_TOKEN_win32: ${{ secrets.TWILIO_AUTH_TOKEN_win32 }} + CONSOLE_EMAIL_darwin: ${{ secrets.CONSOLE_EMAIL_darwin }} + TWILIO_ACCOUNT_SID_darwin: ${{ secrets.TWILIO_ACCOUNT_SID_darwin }} + TWILIO_AUTH_TOKEN_darwin: ${{ secrets.TWILIO_AUTH_TOKEN_darwin }} + SLACK_WEB_HOOK: ${{ secrets.SLACK_WEB_HOOK }} + + scheduled-e2e-wp5-windows: + if: github.event.schedule == '15 8 * * *' + uses: ./.github/workflows/~reusable_e2e_by_OS.yaml + with: + OS: windows-latest-large + BRANCH: main + NPM_IGNORE_PREFIX: ${{ vars.NPM_IGNORE_PREFIX }} + NODE_VERSION: '22' + WP5: true + PACKAGE_VERSION: latest + FLEX_UI_VERSION: latest + SLACK_TITLE: 'Flex Plugins CLI - E2E Nightly - WebPack5' + SEND_NOTIFICATION: true + secrets: + CONSOLE_EMAIL: ${{ secrets.CONSOLE_EMAIL }} + CONSOLE_PASSWORD: ${{ secrets.CONSOLE_PASSWORD }} + CONSOLE_EMAIL_linux: ${{ secrets.CONSOLE_EMAIL_linux }} + TWILIO_ACCOUNT_SID_linux: ${{ secrets.TWILIO_ACCOUNT_SID_linux }} + TWILIO_AUTH_TOKEN_linux: ${{ secrets.TWILIO_AUTH_TOKEN_linux }} + CONSOLE_EMAIL_win32: ${{ secrets.CONSOLE_EMAIL_win32 }} + TWILIO_ACCOUNT_SID_win32: ${{ secrets.TWILIO_ACCOUNT_SID_win32 }} + TWILIO_AUTH_TOKEN_win32: ${{ secrets.TWILIO_AUTH_TOKEN_win32 }} + CONSOLE_EMAIL_darwin: ${{ secrets.CONSOLE_EMAIL_darwin }} + TWILIO_ACCOUNT_SID_darwin: ${{ secrets.TWILIO_ACCOUNT_SID_darwin }} + TWILIO_AUTH_TOKEN_darwin: ${{ secrets.TWILIO_AUTH_TOKEN_darwin }} + SLACK_WEB_HOOK: ${{ secrets.SLACK_WEB_HOOK }} diff --git a/.github/workflows/lockfile_hygiene.yaml b/.github/workflows/lockfile_hygiene.yaml new file mode 100644 index 000000000..009b8a091 --- /dev/null +++ b/.github/workflows/lockfile_hygiene.yaml @@ -0,0 +1,51 @@ +name: Lockfile Hygiene + +# ADR 1634 Rule 3b — keep this public repo resolvable by external consumers. +# CI jobs redirect npm to Artifactory at build time (the artifactory-oidc +# action writes ~/.npmrc); the committed .npmrc / package-lock.json must +# always point at the public registry. Both jobs are secret-less and resolve +# from registry.npmjs.org only (no Artifactory, no OIDC). +# +# No paths-ignore: lockfile-only changes are exactly what this must check. + +on: + pull_request: + branches: + - main + push: + branches: + - main + workflow_dispatch: + +permissions: + contents: read + +jobs: + detect: + name: Detect Artifactory hosts + runs-on: ubuntu-x64 + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + - name: Scan committed lockfiles & resolver config + run: bash .github/scripts/lockfile-hygiene.sh + + clean-room-resolve: + name: Clean-room public resolve + runs-on: ubuntu-x64 + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 + with: + node-version: '22' + - name: Strip any resolver config (simulate an external consumer) + run: | + rm -f ~/.npmrc || true + echo "registry=https://registry.npmjs.org/" > ~/.npmrc + echo "Effective npm registry:" + npm config get registry + - name: Clean-room install from the committed lockfile + env: + npm_config_registry: https://registry.npmjs.org/ + run: | + npm ci --ignore-scripts --no-audit --fund=false + echo "✓ Lockfile resolves against the public registry." diff --git a/.github/workflows/pr_e2e_wp5.yaml b/.github/workflows/pr_e2e_wp5.yaml new file mode 100644 index 000000000..a46136e7f --- /dev/null +++ b/.github/workflows/pr_e2e_wp5.yaml @@ -0,0 +1,63 @@ +name: PR Validator - E2E - WebPack5 (Node 22) + +on: + pull_request: + types: [ labeled ] + +jobs: + get-version: + if: ${{ github.event.label.name == vars.E2E_LABEL }} + runs-on: ubuntu-latest-large + outputs: + branch: ${{ steps.extractBranch.outputs.branch }} + steps: + - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 + with: + node-version: '22' + - name: Extract branch name + run: | + echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" + echo "branch=${GITHUB_HEAD_REF:-${GITHUB_REF#refs/heads/}}" >> $GITHUB_OUTPUT + id: extractBranch + + e2e-test: + needs: get-version + uses: ./.github/workflows/~reusable_e2e_all_OS.yaml + if: ${{ github.event.label.name == vars.E2E_LABEL }} + with: + BRANCH: ${{ needs.get-version.outputs.branch }} + NPM_IGNORE_PREFIX: ${{ vars.NPM_IGNORE_PREFIX }} + NODE_VERSION: '22' + WP5: true + # wp5 never publishes an alpha, so it always exercises the released plugin + PACKAGE_VERSION: latest + FLEX_UI_VERSION: latest + SLACK_TITLE: 'Flex Plugins CLI - E2E - WebPack5' + SEND_NOTIFICATION: false + secrets: + CONSOLE_EMAIL: ${{ secrets.CONSOLE_EMAIL }} + CONSOLE_PASSWORD: ${{ secrets.CONSOLE_PASSWORD }} + CONSOLE_EMAIL_linux: ${{ secrets.CONSOLE_EMAIL_linux }} + TWILIO_ACCOUNT_SID_linux: ${{ secrets.TWILIO_ACCOUNT_SID_linux }} + TWILIO_AUTH_TOKEN_linux: ${{ secrets.TWILIO_AUTH_TOKEN_linux }} + CONSOLE_EMAIL_win32: ${{ secrets.CONSOLE_EMAIL_win32 }} + TWILIO_ACCOUNT_SID_win32: ${{ secrets.TWILIO_ACCOUNT_SID_win32 }} + TWILIO_AUTH_TOKEN_win32: ${{ secrets.TWILIO_AUTH_TOKEN_win32 }} + CONSOLE_EMAIL_darwin: ${{ secrets.CONSOLE_EMAIL_darwin }} + TWILIO_ACCOUNT_SID_darwin: ${{ secrets.TWILIO_ACCOUNT_SID_darwin }} + TWILIO_AUTH_TOKEN_darwin: ${{ secrets.TWILIO_AUTH_TOKEN_darwin }} + SLACK_WEB_HOOK: ${{ secrets.SLACK_WEB_HOOK }} + + remove-label-on-failure: + needs: e2e-test + if: always() + runs-on: ubuntu-latest-large + steps: + - name: Remove label on failure + # Only on an actual failure. `!= 'success'` also matched skipped, so any + # unrelated label added to the PR triggered this job and got removed. + if: needs.e2e-test.result == 'failure' + run: gh pr edit ${{ github.event.pull_request.number }} --repo ${{ github.repository }} --remove-label "${{ github.event.label.name }}" + env: + GH_TOKEN: ${{ github.token }} diff --git a/.github/workflows/pr_workflow.yaml b/.github/workflows/pr_workflow.yaml index 12bc9cf6b..444af3939 100644 --- a/.github/workflows/pr_workflow.yaml +++ b/.github/workflows/pr_workflow.yaml @@ -8,6 +8,7 @@ on: - 'lerna.json' - '**/package-lock.json' - '**/package.json' + workflow_dispatch: push: branches: - main @@ -16,6 +17,9 @@ on: - '**/package-lock.json' - '**/package.json' +env: + ARTIFACTORY_URL: ${{ vars.ARTIFACTORY_URL }} + jobs: build-and-test: runs-on: ubuntu-x64 diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 71b626f23..22ac7d280 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -85,7 +85,12 @@ jobs: # client-id: ${{ secrets.APP_ID }} # private_key: ${{ secrets.APP_KEY }} # + # Check out the branch being released. Without a ref, checkout builds the + # ref the workflow was dispatched from, so releasing a branch while + # dispatching from main published main's code under the branch's name. - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 + with: + ref: ${{ inputs.BRANCH }} # No registry-url on purpose. Given one, setup-node writes an .npmrc with # //registry.npmjs.org/:_authToken=${NODE_AUTH_TOKEN} and, with no token diff --git a/.github/workflows/~reusable_e2e_all_OS.yaml b/.github/workflows/~reusable_e2e_all_OS.yaml index ae84fe0fa..be0b729ac 100644 --- a/.github/workflows/~reusable_e2e_all_OS.yaml +++ b/.github/workflows/~reusable_e2e_all_OS.yaml @@ -17,6 +17,16 @@ on: description: 'A npm-ignore-prefix passed from the caller workflow.' required: true type: string + NODE_VERSION: + description: 'A node-version passed from the caller workflow. It decides the version of node on which tests will run.' + required: false + type: string + default: '22' + WP5: + description: 'A flag passed from the caller workflow, it decides whether the plugins are built/started with webpack 5 (--wp5).' + required: false + type: boolean + default: false SLACK_TITLE: description: 'A title passed from the caller workflow, it will be used in slack notification.' required: false @@ -98,7 +108,8 @@ jobs: NPM_IGNORE_PREFIX: ${{ inputs.NPM_IGNORE_PREFIX }} PACKAGE_VERSION: ${{ inputs.PACKAGE_VERSION }} FLEX_UI_VERSION: ${{ inputs.FLEX_UI_VERSION }} - NODE_VERSION: '22' + NODE_VERSION: ${{ inputs.NODE_VERSION }} + WP5: ${{ inputs.WP5 }} SEND_NOTIFICATION: ${{ inputs.SEND_NOTIFICATION }} SLACK_TITLE: ${{ inputs.SLACK_TITLE }} SLACK_MESSAGE: ${{ inputs.SLACK_MESSAGE }} diff --git a/.github/workflows/~reusable_e2e_by_OS.yaml b/.github/workflows/~reusable_e2e_by_OS.yaml index 4c37fece6..0a9077216 100644 --- a/.github/workflows/~reusable_e2e_by_OS.yaml +++ b/.github/workflows/~reusable_e2e_by_OS.yaml @@ -18,6 +18,11 @@ on: required: false type: string default: '22' + WP5: + description: 'A flag passed from the caller workflow, it decides whether the plugins are built/started with webpack 5 (--wp5).' + required: false + type: boolean + default: false NPM_IGNORE_PREFIX: description: 'A npm-ignore-prefix passed from the caller workflow.' required: true @@ -81,6 +86,7 @@ env: NPM_IGNORE_PREFIX: ${{ inputs.NPM_IGNORE_PREFIX }} PACKAGE_VERSION: ${{ inputs.PACKAGE_VERSION }} FLEX_UI_VERSION: ${{ inputs.FLEX_UI_VERSION }} + WP5: ${{ inputs.WP5 && '1' || '0' }} CONSOLE_EMAIL: ${{ secrets.CONSOLE_EMAIL }} CONSOLE_PASSWORD: ${{ secrets.CONSOLE_PASSWORD }} CONSOLE_EMAIL_linux: ${{ secrets.CONSOLE_EMAIL_linux }} @@ -97,21 +103,24 @@ env: jobs: node: runs-on: ${{ inputs.OS }} + permissions: + contents: read steps: - uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4 - uses: actions/setup-node@249970729cb0ef3589644e2896645e5dc5ba9c38 # v6 with: node-version: ${{ inputs.NODE_VERSION }} - - name: Override localhost to IPv4 in Linux for Node 18 - run: | - sudo sed -i '/localhost/s/::1/#::1/' /etc/hosts - if: ${{ inputs.OS == 'ubuntu-latest-large' && inputs.NODE_VERSION == '18' }} - name: Install project dependencies (Linux) if: ${{ inputs.OS == 'ubuntu-latest-large' }} run: | echo "Starting npm ci with a 10-minute timeout" for i in 1 2 3; do # Retry logic, retry 3 times - timeout 10m npm ci --verbose && break || echo "npm ci failed, retrying ($i/3)..." + timeout 10m npm ci --verbose && break + if [ "$i" -eq 3 ]; then + echo "::error::npm ci failed after 3 attempts" + exit 1 + fi + echo "npm ci failed, retrying ($i/3)..." done - name: Install project dependencies (Macos) if: ${{ inputs.OS == 'macos-x64' }} @@ -119,7 +128,12 @@ jobs: echo "Starting npm ci with a 10-minute timeout" brew install coreutils for i in 1 2 3; do # Retry logic, retry 3 times - gtimeout 10m npm ci --verbose && break || echo "npm ci failed, retrying ($i/3)..." + gtimeout 10m npm ci --verbose && break + if [ "$i" -eq 3 ]; then + echo "::error::npm ci failed after 3 attempts" + exit 1 + fi + echo "npm ci failed, retrying ($i/3)..." done - name: Install project dependencies (Windows) if: ${{ inputs.OS == 'windows-latest-large' }} diff --git a/.husky/pre-commit b/.husky/pre-commit index ace42643e..8750ec6a7 100755 --- a/.husky/pre-commit +++ b/.husky/pre-commit @@ -1,4 +1,5 @@ #!/bin/sh . "$(dirname "$0")/_/husky.sh" +node .github/scripts/public-lockfile.js ./node_modules/.bin/ultra lint diff --git a/link-packages.js b/link-packages.js index 03d28cc99..5e76e20f4 100755 --- a/link-packages.js +++ b/link-packages.js @@ -128,7 +128,9 @@ function linkDependencies(packages) { for (const depName of localDependencies) { try { log(`${colors.cyan} Linking ${depName} to ${pkg.name}...${colors.reset}`, colors.cyan); - execCommand(`npm link "${depName}"`, pkg.path); + // --force is needed because this repo has pre-existing, unrelated peer dependency + // conflicts (react 16 vs 17) that npm's strict resolver refuses to auto-resolve. + execCommand(`npm link "${depName}" --force`, pkg.path); log(`${colors.green} ✓ Successfully linked ${depName} to ${pkg.name}${colors.reset}`, colors.green); } catch (error) { log(`${colors.red} ✗ Failed to link ${depName} to ${pkg.name}${colors.reset}`, colors.red); diff --git a/package-lock.json b/package-lock.json index aa5acf285..2b77583e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -913,6 +913,23 @@ "@babel/core": "^7.0.0-0" } }, + "node_modules/@babel/plugin-proposal-unicode-property-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.18.6.tgz", + "integrity": "sha512-2BShG/d5yoZyXZfVePH91urL5wTG6ASZU9M4o03lKK8u8UW1y08OMttBSOADTcJrnPMpvDXRG3G8fyLh4ovs8w==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-unicode-property-regex instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, "node_modules/@babel/plugin-syntax-async-generators": { "version": "7.8.4", "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz", @@ -2242,6 +2259,22 @@ "semver": "bin/semver.js" } }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6.tgz", + "integrity": "sha512-ID2yj6K/4lKfhuU3+EX4UvNbIt7eACFbHmNUjzA+ep+B5971CknnA/9DEWKbRokfbbtblxxxXFJJrH47UEAMVg==", + "license": "MIT", + "dependencies": { + "@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" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/@babel/preset-react": { "version": "7.29.7", "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.29.7.tgz", @@ -2416,6 +2449,15 @@ "node": "^14 || ^16 || >=18" } }, + "node_modules/@csstools/convert-colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@csstools/convert-colors/-/convert-colors-1.4.0.tgz", + "integrity": "sha512-5a6wqoJV/xEdbRNKVo6I4hO3VjyDq//8q2f9I6PBAvMesJHFauXDorcNCsr9RzvsZnaWi5NYCcfyqP1QeFHFbw==", + "license": "CC0-1.0", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/@csstools/css-calc": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@csstools/css-calc/-/css-calc-1.2.0.tgz", @@ -12297,6 +12339,10 @@ "resolved": "packages/flex-plugin-webpack", "link": true }, + "node_modules/@twilio/flex-plugin-webpack5": { + "resolved": "packages/flex-plugin-webpack5", + "link": true + }, "node_modules/@twilio/flex-plugins-api-client": { "resolved": "packages/flex-plugins-api-client", "link": true @@ -12758,6 +12804,32 @@ "@types/react": "*" } }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.9.tgz", + "integrity": "sha512-GhdPgy1el4/ImP05X05Uw4cw2/M93BCUmnEvWZNStlCzEKME4Fkk+YpoA5OiHNQmoS7Cafb8Xa3Pya8m1Qrzeg==", + "license": "MIT" + }, "node_modules/@types/events": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/@types/events/-/events-3.0.3.tgz", @@ -13405,6 +13477,18 @@ "terser": "^4.3.9" } }, + "node_modules/@types/terser-webpack-plugin-wp5": { + "name": "@types/terser-webpack-plugin", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@types/terser-webpack-plugin/-/terser-webpack-plugin-2.2.3.tgz", + "integrity": "sha512-IqmP1OBzNyx9ZNj/3Svf0QFN+cJUrtECceVLENlXhXX4snmkgxo8n3U3wMJv1c066FXqwP+iorzCZCJhshytsw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/webpack": "^4", + "terser": "^4.3.9" + } + }, "node_modules/@types/through": { "version": "0.0.30", "resolved": "https://registry.npmjs.org/@types/through/-/through-0.0.30.tgz", @@ -13890,6 +13974,29 @@ "@webassemblyjs/ast": "1.9.0" } }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-numbers/node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers/node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "license": "MIT" + }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.9.0", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz", @@ -17484,6 +17591,12 @@ "dev": true, "license": "ISC" }, + "node_modules/common-path-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz", + "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==", + "license": "ISC" + }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", @@ -18238,6 +18351,61 @@ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" }, + "node_modules/copy-concurrently": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz", + "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "aproba": "^1.1.1", + "fs-write-stream-atomic": "^1.0.8", + "iferr": "^0.1.5", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.0" + } + }, + "node_modules/copy-concurrently/node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "license": "ISC" + }, + "node_modules/copy-concurrently/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/copy-concurrently/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/copy-descriptor": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz", @@ -19474,6 +19642,22 @@ "webpack": "^1 || ^2 || ^3 || ^4 || ^5" } }, + "node_modules/dotenv-webpack-wp5": { + "name": "dotenv-webpack", + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/dotenv-webpack/-/dotenv-webpack-8.1.1.tgz", + "integrity": "sha512-+TY/AJ2k9bU2EML3mxgLmaAvEcqs1Wbv6deCIUSI3eW3Xeo8LBQumYib6puyaSwbjC9JCzg/y5Pwjd/lePX04w==", + "license": "MIT", + "dependencies": { + "dotenv-defaults": "^2.0.2" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "webpack": "^4 || ^5" + } + }, "node_modules/downshift": { "version": "6.1.7", "resolved": "https://registry.npmjs.org/downshift/-/downshift-6.1.7.tgz", @@ -19877,6 +20061,12 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", + "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", + "license": "MIT" + }, "node_modules/es-object-atoms": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.2.tgz", @@ -20504,7 +20694,6 @@ "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", @@ -21608,6 +21797,22 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-uri": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.8.tgz", + "integrity": "sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fast-url-parser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", @@ -21711,6 +21916,13 @@ "node": ">=8" } }, + "node_modules/figgy-pudding": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz", + "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==", + "deprecated": "This module is no longer supported.", + "license": "ISC" + }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", @@ -21964,6 +22176,13 @@ "dev": true, "license": "ISC" }, + "node_modules/flatten": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/flatten/-/flatten-1.0.3.tgz", + "integrity": "sha512-dVsPA/UwQ8+2uoFe5GHtiBMu48dWLTdsuEd7CKGlZlD78r1TTWBvDuFaFGKCo/ZfEr95Uk56vZoX86OsHkUeIg==", + "deprecated": "flatten is deprecated in favor of utility frameworks such as lodash.", + "license": "MIT" + }, "node_modules/focus-lock": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/focus-lock/-/focus-lock-1.3.6.tgz", @@ -22203,6 +22422,19 @@ "dev": true, "license": "MIT" }, + "node_modules/fs-write-stream-atomic": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", + "integrity": "sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "graceful-fs": "^4.1.2", + "iferr": "^0.1.5", + "imurmurhash": "^0.1.4", + "readable-stream": "1 || 2" + } + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -22808,6 +23040,12 @@ "node": ">= 6" } }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "license": "BSD-2-Clause" + }, "node_modules/glob/node_modules/brace-expansion": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", @@ -24104,6 +24342,12 @@ } ] }, + "node_modules/iferr": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz", + "integrity": "sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==", + "license": "MIT" + }, "node_modules/ignore": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", @@ -24259,6 +24503,12 @@ "node": ">=8" } }, + "node_modules/indexes-of": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz", + "integrity": "sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA==", + "license": "MIT" + }, "node_modules/infer-owner": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", @@ -28955,6 +29205,15 @@ "node": ">=8" } }, + "node_modules/jiti": { + "version": "1.21.7", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", + "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", + "license": "MIT", + "bin": { + "jiti": "bin/jiti.js" + } + }, "node_modules/js-message": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz", @@ -31344,6 +31603,61 @@ "dev": true, "license": "MIT" }, + "node_modules/move-concurrently": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", + "integrity": "sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "aproba": "^1.1.1", + "copy-concurrently": "^1.0.0", + "fs-write-stream-atomic": "^1.0.8", + "mkdirp": "^0.5.1", + "rimraf": "^2.5.4", + "run-queue": "^1.0.3" + } + }, + "node_modules/move-concurrently/node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "license": "ISC" + }, + "node_modules/move-concurrently/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/move-concurrently/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, "node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", @@ -31534,6 +31848,12 @@ "node": ">=10" } }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "license": "MIT" + }, "node_modules/node-addon-api": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-3.2.1.tgz", @@ -32278,6 +32598,12 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, + "node_modules/num2fraction": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz", + "integrity": "sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==", + "license": "MIT" + }, "node_modules/nwsapi": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/nwsapi/-/nwsapi-2.2.0.tgz", @@ -34258,6 +34584,52 @@ "postcss": "^8.4" } }, + "node_modules/postcss-color-gray": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-color-gray/-/postcss-color-gray-5.0.0.tgz", + "integrity": "sha512-q6BuRnAGKM/ZRpfDascZlIZPjvwsRye7UDNalqVz3s7GDxMtqPY6+Q871liNxsonUw8oC61OG+PSaysYpl1bnw==", + "license": "ISC", + "dependencies": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-color-gray/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "license": "ISC" + }, + "node_modules/postcss-color-gray/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-color-gray/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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/postcss-color-hex-alpha": { "version": "9.0.4", "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-9.0.4.tgz", @@ -34283,6 +34655,52 @@ "postcss": "^8.4" } }, + "node_modules/postcss-color-mod-function": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-mod-function/-/postcss-color-mod-function-3.0.3.tgz", + "integrity": "sha512-YP4VG+xufxaVtzV6ZmhEtc+/aTXH3d0JLpnYfxqTvwZPbJhWqp8bSY3nfNzNRFLgB4XSaBA82OE4VjOOKpCdVQ==", + "license": "CC0-1.0", + "dependencies": { + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-color-mod-function/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "license": "ISC" + }, + "node_modules/postcss-color-mod-function/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-color-mod-function/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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/postcss-color-rebeccapurple": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-9.0.3.tgz", @@ -34440,6 +34858,51 @@ "postcss": "^8.4" } }, + "node_modules/postcss-env-function": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-2.0.2.tgz", + "integrity": "sha512-rwac4BuZlITeUbiBq60h/xbLzXY43qOsIErngWa4l7Mt+RaSkT7QBjXVGTcBHupykkblHMDrBFh30zchYPaOUw==", + "license": "CC0-1.0", + "dependencies": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-env-function/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "license": "ISC" + }, + "node_modules/postcss-env-function/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-env-function/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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/postcss-flexbugs-fixes": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/postcss-flexbugs-fixes/-/postcss-flexbugs-fixes-5.0.2.tgz", @@ -34550,6 +35013,47 @@ "postcss": "^8.4" } }, + "node_modules/postcss-initial": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-3.0.4.tgz", + "integrity": "sha512-3RLn6DIpMsK1l5UUy9jxQvoDeUN4gP939tDcKUHD/kM8SGSKbFAnvkpFpj3Bhtz3HGk1jWY5ZNWX6mPta5M9fg==", + "license": "MIT", + "dependencies": { + "postcss": "^7.0.2" + } + }, + "node_modules/postcss-initial/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "license": "ISC" + }, + "node_modules/postcss-initial/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-initial/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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/postcss-lab-function": { "version": "6.0.12", "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-6.0.12.tgz", @@ -34656,6 +35160,50 @@ "postcss": "^8.4" } }, + "node_modules/postcss-media-minmax": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-4.0.0.tgz", + "integrity": "sha512-fo9moya6qyxsjbFAYl97qKO9gyre3qvbMnkOZeZwlsW6XYFsvs2DMGDlchVLfAd8LHPZDxivu/+qW2SMQeTHBw==", + "license": "MIT", + "dependencies": { + "postcss": "^7.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/postcss-media-minmax/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "license": "ISC" + }, + "node_modules/postcss-media-minmax/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-media-minmax/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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/postcss-modules-extract-imports": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", @@ -34958,6 +35506,48 @@ "postcss": "^8.0.3" } }, + "node_modules/postcss-selector-matches": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-matches/-/postcss-selector-matches-4.0.0.tgz", + "integrity": "sha512-LgsHwQR/EsRYSqlwdGzeaPKVT0Ml7LAT6E75T8W8xLJY62CE4S/l03BWIt3jT8Taq22kXP08s2SfTSzaraoPww==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" + } + }, + "node_modules/postcss-selector-matches/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "license": "ISC" + }, + "node_modules/postcss-selector-matches/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/postcss-selector-matches/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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/postcss-selector-not": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-7.0.2.tgz", @@ -34999,6 +35589,20 @@ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" }, + "node_modules/postcss-values-parser": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-2.0.1.tgz", + "integrity": "sha512-2tLuBsA6P4rYTNKCXYG/71C7j1pU6pK503suYOmn4xYrQIzW+opD+7FAFNuGSdZC/3Qfy334QbeMu7MEb8gOxg==", + "license": "MIT", + "dependencies": { + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=6.14.4" + } + }, "node_modules/prebuild-install": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.1.tgz", @@ -37405,6 +38009,21 @@ "queue-microtask": "^1.2.2" } }, + "node_modules/run-queue": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", + "integrity": "sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg==", + "license": "ISC", + "dependencies": { + "aproba": "^1.1.1" + } + }, + "node_modules/run-queue/node_modules/aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==", + "license": "ISC" + }, "node_modules/rxjs": { "version": "6.6.7", "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", @@ -39485,6 +40104,204 @@ "webpack": "^4.0.0 || ^5.0.0" } }, + "node_modules/terser-webpack-plugin-wp5": { + "name": "terser-webpack-plugin", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz", + "integrity": "sha512-/fKw3R+hWyHfYx7Bv6oPqmk4HGQcrWLtV3X6ggvPuwPNHSnzvVV51z6OaaCOus4YLjutYGOz3pEpbhe6Up2s1w==", + "license": "MIT", + "dependencies": { + "cacache": "^13.0.1", + "find-cache-dir": "^3.3.1", + "jest-worker": "^25.4.0", + "p-limit": "^2.3.0", + "schema-utils": "^2.6.6", + "serialize-javascript": "^4.0.0", + "source-map": "^0.6.1", + "terser": "^4.6.12", + "webpack-sources": "^1.4.3" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/terser-webpack-plugin-wp5/node_modules/cacache": { + "version": "13.0.1", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-13.0.1.tgz", + "integrity": "sha512-5ZvAxd05HDDU+y9BVvcqYu2LLXmPnQ0hW62h32g4xBTgL/MppR4/04NHfj/ycM2y6lmTnbw6HVi+1eN0Psba6w==", + "license": "ISC", + "dependencies": { + "chownr": "^1.1.2", + "figgy-pudding": "^3.5.1", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "graceful-fs": "^4.2.2", + "infer-owner": "^1.0.4", + "lru-cache": "^5.1.1", + "minipass": "^3.0.0", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^0.5.1", + "move-concurrently": "^1.0.1", + "p-map": "^3.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^2.7.1", + "ssri": "^7.0.0", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/terser-webpack-plugin-wp5/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "license": "ISC" + }, + "node_modules/terser-webpack-plugin-wp5/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/terser-webpack-plugin-wp5/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/terser-webpack-plugin-wp5/node_modules/jest-worker": { + "version": "25.5.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-25.5.0.tgz", + "integrity": "sha512-/dsSmUkIy5EBGfv/IjjqmFxrNAUpBERfGs1oHROyD7yxjG/w+t0GOJDX8O1k32ySmd7+a5IhnJU2qQFcJ4n1vw==", + "license": "MIT", + "dependencies": { + "merge-stream": "^2.0.0", + "supports-color": "^7.0.0" + }, + "engines": { + "node": ">= 8.3" + } + }, + "node_modules/terser-webpack-plugin-wp5/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==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/terser-webpack-plugin-wp5/node_modules/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==", + "license": "MIT", + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/terser-webpack-plugin-wp5/node_modules/rimraf": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz", + "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/terser-webpack-plugin-wp5/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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/terser-webpack-plugin-wp5/node_modules/ssri": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.1.tgz", + "integrity": "sha512-w+daCzXN89PseTL99MkA+fxJEcU3wfaE/ah0i0lnOlpG1CYLJ2ZjzEry68YBKfLs4JfoTShrTEsJkAZuNZ/stw==", + "license": "ISC", + "dependencies": { + "figgy-pudding": "^3.5.1", + "minipass": "^3.1.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/terser-webpack-plugin-wp5/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/terser-webpack-plugin-wp5/node_modules/unique-filename": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", + "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", + "license": "ISC", + "dependencies": { + "unique-slug": "^2.0.0" + } + }, + "node_modules/terser-webpack-plugin-wp5/node_modules/unique-slug": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", + "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4" + } + }, + "node_modules/terser-webpack-plugin-wp5/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, "node_modules/terser-webpack-plugin/node_modules/@npmcli/fs": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", @@ -40350,7 +41167,6 @@ "version": "4.9.5", "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "devOptional": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", @@ -40693,6 +41509,12 @@ "node": ">=0.10.0" } }, + "node_modules/uniq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz", + "integrity": "sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==", + "license": "MIT" + }, "node_modules/unique-filename": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", @@ -41629,6 +42451,166 @@ } } }, + "node_modules/webpack-dev-server-wp5": { + "name": "webpack-dev-server", + "version": "4.15.2", + "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz", + "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==", + "license": "MIT", + "dependencies": { + "@types/bonjour": "^3.5.9", + "@types/connect-history-api-fallback": "^1.3.5", + "@types/express": "^4.17.13", + "@types/serve-index": "^1.9.1", + "@types/serve-static": "^1.13.10", + "@types/sockjs": "^0.3.33", + "@types/ws": "^8.5.5", + "ansi-html-community": "^0.0.8", + "bonjour-service": "^1.0.11", + "chokidar": "^3.5.3", + "colorette": "^2.0.10", + "compression": "^1.7.4", + "connect-history-api-fallback": "^2.0.0", + "default-gateway": "^6.0.3", + "express": "^4.17.3", + "graceful-fs": "^4.2.6", + "html-entities": "^2.3.2", + "http-proxy-middleware": "^2.0.3", + "ipaddr.js": "^2.0.1", + "launch-editor": "^2.6.0", + "open": "^8.0.9", + "p-retry": "^4.5.0", + "rimraf": "^3.0.2", + "schema-utils": "^4.0.0", + "selfsigned": "^2.1.1", + "serve-index": "^1.9.1", + "sockjs": "^0.3.24", + "spdy": "^4.0.2", + "webpack-dev-middleware": "^5.3.4", + "ws": "^8.13.0" + }, + "bin": { + "webpack-dev-server": "bin/webpack-dev-server.js" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.37.0 || ^5.0.0" + }, + "peerDependenciesMeta": { + "webpack": { + "optional": true + }, + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server-wp5/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack-dev-server-wp5/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/webpack-dev-server-wp5/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack-dev-server-wp5/node_modules/ipaddr.js": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.5.0.tgz", + "integrity": "sha512-aq+t5NAc+cS6rZQQVWC2x98CPqGtKKTMDd4Gaodv0wShnItdKg/51djkGJ1hqH+Oy0ivDftCbSLCQob8zso01w==", + "license": "MIT", + "engines": { + "node": ">= 10" + } + }, + "node_modules/webpack-dev-server-wp5/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "node_modules/webpack-dev-server-wp5/node_modules/schema-utils": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.5.0.tgz", + "integrity": "sha512-zJlMCZ0cAR5p/Y4oVpRoqioDMJcGxaXRrQ/4rP4WyR84vc5z/DolXdbvXeDpTwbtocDFr2rhPqHPErDCUtz2kA==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.15", + "ajv": "^8.20.0", + "ajv-formats": "^3.0.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack-dev-server-wp5/node_modules/ws": { + "version": "8.22.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.22.0.tgz", + "integrity": "sha512-Ydggc987+RO0AnWtZ/7Wq9FtNvcrL1b/RO0ud9mWjUPgDrsAAwQSF51sm2hm1XofbU/4jkpGEsLFsZZxU+1DOg==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/webpack-dev-server/node_modules/ajv": { "version": "8.12.0", "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", @@ -41802,1784 +42784,4622 @@ "webpack": "^4.0.0" } }, - "node_modules/websocket-driver": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", - "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "node_modules/webpack5": { + "name": "webpack", + "version": "5.88.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", + "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", + "license": "MIT", "dependencies": { - "http-parser-js": ">=0.5.1", - "safe-buffer": ">=5.1.0", - "websocket-extensions": ">=0.1.1" + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" }, "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/websocket-extensions": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", - "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", - "engines": { - "node": ">=0.8.0" + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } } }, - "node_modules/whatwg-encoding": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", - "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "node_modules/webpack5/node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", "license": "MIT", "dependencies": { - "iconv-lite": "0.4.24" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, - "node_modules/whatwg-fetch": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", - "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==", + "node_modules/webpack5/node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", "license": "MIT" }, - "node_modules/whatwg-mimetype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", - "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "node_modules/webpack5/node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", "license": "MIT" }, - "node_modules/whatwg-url": { - "version": "8.4.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.4.0.tgz", - "integrity": "sha512-vwTUFf6V4zhcPkWp/4CQPr1TW9Ml6SF4lVyaIMBdJw5i6qUUJ1QWM4Z6YYVkfka0OUIzVo/0aNtGVGk256IKWw==", - "license": "MIT", - "dependencies": { - "lodash.sortby": "^4.7.0", - "tr46": "^2.1.0", - "webidl-conversions": "^6.1.0" - }, - "engines": { - "node": ">=10" - } + "node_modules/webpack5/node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "license": "MIT" }, - "node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/webpack5/node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" } }, - "node_modules/which-boxed-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "node_modules/webpack5/node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", "license": "MIT", "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@xtuc/ieee754": "^1.2.0" } }, - "node_modules/which-builtin-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", - "license": "MIT", + "node_modules/webpack5/node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "license": "Apache-2.0", "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@xtuc/long": "4.2.2" } }, - "node_modules/which-builtin-type/node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "node_modules/webpack5/node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", "license": "MIT" }, - "node_modules/which-collection": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "node_modules/webpack5/node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", "license": "MIT", "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" } }, - "node_modules/which-module": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", - "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", - "dev": true - }, - "node_modules/which-typed-array": { - "version": "1.1.24", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.24.tgz", - "integrity": "sha512-wk4Mf4pR5mRP7eYuuTBCIQ9d0ud2Fv2jRLQpfgnRjbOxAFHmjKFValgTpitVKzJJS8ajnYQV2Du1SZ8j6b/EUQ==", + "node_modules/webpack5/node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.9", - "call-bound": "^1.0.4", - "for-each": "^0.3.5", - "get-proto": "^1.0.1", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, - "node_modules/widest-line": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", - "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "node_modules/webpack5/node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "license": "MIT", "dependencies": { - "string-width": "^4.0.0" - }, - "engines": { - "node": ">=8" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" } }, - "node_modules/word-wrap": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", - "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", - "dev": true, + "node_modules/webpack5/node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "license": "MIT" - }, - "node_modules/worker-farm": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", - "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", "dependencies": { - "errno": "~0.1.7" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" } }, - "node_modules/worker-rpc": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/worker-rpc/-/worker-rpc-0.1.1.tgz", - "integrity": "sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg==", + "node_modules/webpack5/node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "license": "MIT", "dependencies": { - "microevent.ts": "~0.1.1" + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" } }, - "node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "node_modules/webpack5/node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">=8" + "node": ">=0.4.0" } }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, + "node_modules/webpack5/node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "deprecated": "package has been renamed to acorn-import-attributes", "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "peerDependencies": { + "acorn": "^8" } }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "node_modules/webpack5/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "ajv": "^8.0.0" }, - "engines": { - "node": ">=8" + "peerDependencies": { + "ajv": "^8.0.0" }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "peerDependenciesMeta": { + "ajv": { + "optional": true + } } }, - "node_modules/wrap-ansi-cjs/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "node_modules/webpack5/node_modules/ajv-formats/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" }, - "engines": { - "node": ">=7.0.0" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/wrap-ansi-cjs/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, + "node_modules/webpack5/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==", "license": "MIT" }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, + "node_modules/webpack5/node_modules/enhanced-resolve": { + "version": "5.25.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.25.1.tgz", + "integrity": "sha512-nGXts5znJzmWPu+mIE9izCOzdg63oJca2mDzGWWTth7sr4aCToKcoyFVBQwN75Ij5Pf6p510EwkTqViTRzDV+w==", "license": "MIT", "dependencies": { - "ansi-regex": "^5.0.1" + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" }, "engines": { - "node": ">=8" + "node": ">=10.13.0" } }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/webpack5/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/webpack5/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">= 10.13.0" } }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + "node_modules/webpack5/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" }, - "node_modules/wrap-ansi/node_modules/strip-ansi": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", - "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "node_modules/webpack5/node_modules/loader-runner": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.0" - }, "engines": { - "node": ">=8" + "node": ">=6.11.5" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" - }, - "node_modules/write-file-atomic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", - "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", - "dependencies": { - "imurmurhash": "^0.1.4", - "is-typedarray": "^1.0.0", - "signal-exit": "^3.0.2", - "typedarray-to-buffer": "^3.1.5" + "node_modules/webpack5/node_modules/mime-db": { + "version": "1.54.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz", + "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==", + "license": "MIT", + "peer": true, + "engines": { + "node": ">= 0.6" } }, - "node_modules/write-json-file": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-4.3.0.tgz", - "integrity": "sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ==", - "dev": true, + "node_modules/webpack5/node_modules/minimizer-webpack-plugin": { + "version": "5.12.0", + "resolved": "https://registry.npmjs.org/minimizer-webpack-plugin/-/minimizer-webpack-plugin-5.12.0.tgz", + "integrity": "sha512-PCN1x1OzFeFB2GlP91s46q7Gz8Jf16Z7M45bzpoqrYZlh12QeY6tYVM5h299wbwy1DxnQ69VFmmh8Hb2Ff8mbw==", "license": "MIT", + "peer": true, "dependencies": { - "detect-indent": "^6.0.0", - "graceful-fs": "^4.1.15", - "is-plain-obj": "^2.0.0", - "make-dir": "^3.0.0", - "sort-keys": "^4.0.0", - "write-file-atomic": "^3.0.0" + "@jridgewell/trace-mapping": "^0.3.31", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.3", + "terser": "^5.51.0" }, "engines": { - "node": ">=8.3" + "node": ">= 10.13.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/write-json-file/node_modules/detect-indent": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", - "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, + "@napi-rs/image": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "html-minifier-terser": { + "optional": true + }, + "imagemin": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, + "sharp": { + "optional": true + }, + "svgo": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/webpack5/node_modules/minimizer-webpack-plugin/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack5/node_modules/minimizer-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack5/node_modules/minimizer-webpack-plugin/node_modules/schema-utils": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.5.0.tgz", + "integrity": "sha512-zJlMCZ0cAR5p/Y4oVpRoqioDMJcGxaXRrQ/4rP4WyR84vc5z/DolXdbvXeDpTwbtocDFr2rhPqHPErDCUtz2kA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.15", + "ajv": "^8.20.0", + "ajv-formats": "^3.0.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack5/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack5/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/webpack5/node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack5/node_modules/terser": { + "version": "5.51.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.51.2.tgz", + "integrity": "sha512-bWnjSNscmuI+GJze6ZupnHP8G/cTcsJF+bXCeQknk2SHQsgbNJnLrqiH9jZ2W4STPVXH2mDKKRX3iwPhc9Cn/Q==", + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/webpack5/node_modules/terser-webpack-plugin": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/webpack5/node_modules/terser-webpack-plugin/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack5/node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack5/node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.5.0.tgz", + "integrity": "sha512-zJlMCZ0cAR5p/Y4oVpRoqioDMJcGxaXRrQ/4rP4WyR84vc5z/DolXdbvXeDpTwbtocDFr2rhPqHPErDCUtz2kA==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.15", + "ajv": "^8.20.0", + "ajv-formats": "^3.0.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/webpack5/node_modules/watchpack": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.2.tgz", + "integrity": "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack5/node_modules/webpack": { + "version": "5.111.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.111.1.tgz", + "integrity": "sha512-cNypaz0RP+S4cvQVi1M/3bRUkvNP0xZpL0TjFx+c6jg64VbxD+2weWDgY9UnjRI6dhZgtaj8DU76GGFcJ79xPQ==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/estree": "^1.0.8", + "@types/json-schema": "^7.0.15", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "browserslist": "^4.28.1", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.25.0", + "es-module-lexer": "^2.1.0", + "events": "^3.2.0", + "graceful-fs": "^4.2.11", + "mime-db": "^1.54.0", + "minimizer-webpack-plugin": "^5.7.0", + "schema-utils": "^4.5.0", + "tapable": "^2.3.0", + "watchpack": "^2.5.2", + "webpack-sources": "^3.5.1" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack5/node_modules/webpack-sources": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.6.0.tgz", + "integrity": "sha512-EIMmPVvNI0CYXyRPp34F2Qk7W37/BZVZIofS6LAUnrNjCVahS+hO4mxwFJDjQjODTGZDtVzLYoN2+1dYkhk9qA==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack5/node_modules/webpack/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/webpack5/node_modules/webpack/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "license": "MIT", + "peer": true, + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/webpack5/node_modules/webpack/node_modules/es-module-lexer": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.3.2.tgz", + "integrity": "sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==", + "license": "MIT", + "peer": true + }, + "node_modules/webpack5/node_modules/webpack/node_modules/schema-utils": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.5.0.tgz", + "integrity": "sha512-zJlMCZ0cAR5p/Y4oVpRoqioDMJcGxaXRrQ/4rP4WyR84vc5z/DolXdbvXeDpTwbtocDFr2rhPqHPErDCUtz2kA==", + "license": "MIT", + "peer": true, + "dependencies": { + "@types/json-schema": "^7.0.15", + "ajv": "^8.20.0", + "ajv-formats": "^3.0.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/websocket-driver": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", + "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==", + "dependencies": { + "http-parser-js": ">=0.5.1", + "safe-buffer": ">=5.1.0", + "websocket-extensions": ">=0.1.1" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/websocket-extensions": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz", + "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/whatwg-encoding": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-1.0.5.tgz", + "integrity": "sha512-b5lim54JOPN9HtzvK9HFXvBma/rnfFeqsic0hSpjtDbVxR3dJKLc+KB4V6GgiGOvl7CY/KNh8rxSo9DKQrnUEw==", + "license": "MIT", + "dependencies": { + "iconv-lite": "0.4.24" + } + }, + "node_modules/whatwg-fetch": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz", + "integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==", + "license": "MIT" + }, + "node_modules/whatwg-mimetype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz", + "integrity": "sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==", + "license": "MIT" + }, + "node_modules/whatwg-url": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-8.4.0.tgz", + "integrity": "sha512-vwTUFf6V4zhcPkWp/4CQPr1TW9Ml6SF4lVyaIMBdJw5i6qUUJ1QWM4Z6YYVkfka0OUIzVo/0aNtGVGk256IKWw==", + "license": "MIT", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^2.1.0", + "webidl-conversions": "^6.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "license": "MIT" + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=", + "dev": true + }, + "node_modules/which-typed-array": { + "version": "1.1.24", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.24.tgz", + "integrity": "sha512-wk4Mf4pR5mRP7eYuuTBCIQ9d0ud2Fv2jRLQpfgnRjbOxAFHmjKFValgTpitVKzJJS8ajnYQV2Du1SZ8j6b/EUQ==", + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.9", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/wide-align": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", + "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^1.0.2 || 2 || 3 || 4" + } + }, + "node_modules/widest-line": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-3.1.0.tgz", + "integrity": "sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg==", + "dependencies": { + "string-width": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "license": "MIT" + }, + "node_modules/worker-farm": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz", + "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==", + "dependencies": { + "errno": "~0.1.7" + } + }, + "node_modules/worker-rpc": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/worker-rpc/-/worker-rpc-0.1.1.tgz", + "integrity": "sha512-P1WjMrUB3qgJNI9jfmpZ/htmBEjFh//6l/5y8SD9hg1Ef5zTTVVoRjTrTEzPrNBQvmhMxkoTsjOXN10GWU7aCg==", + "dependencies": { + "microevent.ts": "~0.1.1" + } + }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/wrap-ansi/node_modules/strip-ansi": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz", + "integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "node_modules/write-file-atomic": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz", + "integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==", + "dependencies": { + "imurmurhash": "^0.1.4", + "is-typedarray": "^1.0.0", + "signal-exit": "^3.0.2", + "typedarray-to-buffer": "^3.1.5" + } + }, + "node_modules/write-json-file": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-4.3.0.tgz", + "integrity": "sha512-PxiShnxf0IlnQuMYOPPhPkhExoCQuTUNPOa/2JWCYTmBquU9njyyDuwRKN26IZBlp4yn1nt+Agh2HOOBl+55HQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-indent": "^6.0.0", + "graceful-fs": "^4.1.15", + "is-plain-obj": "^2.0.0", + "make-dir": "^3.0.0", + "sort-keys": "^4.0.0", + "write-file-atomic": "^3.0.0" + }, + "engines": { + "node": ">=8.3" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/write-json-file/node_modules/detect-indent": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", + "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/write-json-file/node_modules/is-plain-obj": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", + "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/write-json-file/node_modules/make-dir": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", + "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^6.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/write-json-file/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/write-pkg": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-4.0.0.tgz", + "integrity": "sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==", + "dev": true, + "license": "MIT", + "dependencies": { + "sort-keys": "^2.0.0", + "type-fest": "^0.4.1", + "write-json-file": "^3.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/write-pkg/node_modules/detect-indent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", + "integrity": "sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/write-pkg/node_modules/sort-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", + "integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-plain-obj": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/write-pkg/node_modules/type-fest": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz", + "integrity": "sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=6" + } + }, + "node_modules/write-pkg/node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/write-pkg/node_modules/write-json-file": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", + "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-indent": "^5.0.0", + "graceful-fs": "^4.1.15", + "make-dir": "^2.1.0", + "pify": "^4.0.1", + "sort-keys": "^2.0.0", + "write-file-atomic": "^2.4.2" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ws": { + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xdg-basedir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", + "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/xml-name-validator": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", + "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", + "license": "Apache-2.0" + }, + "node_modules/xmlbuilder": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", + "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==", + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, + "node_modules/xmlchars": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", + "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "license": "MIT" + }, + "node_modules/xmlhttprequest": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", + "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", + "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==" + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/yamljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", + "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "glob": "^7.0.5" + }, + "bin": { + "json2yaml": "bin/json2yaml", + "yaml2json": "bin/yaml2json" + } + }, + "node_modules/yamljs/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "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" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/yarn": { + "version": "1.22.19", + "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.19.tgz", + "integrity": "sha512-/0V5q0WbslqnwP91tirOvldvYISzaqhClxzyUKXYxs07yUILIs5jx/k6CFe8bvKSkds5w+eiOqta39Wk3WxdcQ==", + "hasInstallScript": true, + "license": "BSD-2-Clause", + "bin": { + "yarn": "bin/yarn.js", + "yarnpkg": "bin/yarn.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/yauzl": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", + "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", + "license": "MIT", + "dependencies": { + "buffer-crc32": "~0.2.3", + "fd-slicer": "~1.1.0" + } + }, + "node_modules/yjs": { + "version": "13.6.33", + "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.33.tgz", + "integrity": "sha512-q/UYvr1gOk4XII+Cu1CW2dINjYqJJFifTzogEaIARznrvX7uOlHsdTEXcnOBMuIsrCGEEKdNxi74kyMLZlKVfw==", + "dev": true, + "license": "MIT", + "peer": true, + "dependencies": { + "lib0": "^0.2.99" + }, + "engines": { + "node": ">=16.0.0", + "npm": ">=8.0.0" + }, + "funding": { + "type": "GitHub Sponsors ❤", + "url": "https://github.com/sponsors/dmonad" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zen-observable": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", + "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/zen-observable-ts": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz", + "integrity": "sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==", + "dev": true, + "license": "MIT", + "dependencies": { + "zen-observable": "0.8.15" + } + }, + "packages/create-flex-plugin": { + "name": "@twilio/create-flex-plugin", + "version": "7.1.3", + "license": "MIT", + "dependencies": { + "@twilio/flex-dev-utils": "7.1.3", + "esm-wallaby": "^3.2.30", + "tmp": "^0.2.1", + "yargs": "^16.2.0" + }, + "bin": { + "create-flex-plugin": "bin/create-flex-plugin" + }, + "devDependencies": { + "@twilio/flex-plugin": "7.1.3", + "@twilio/flex-plugin-scripts": "7.1.3", + "@types/tmp": "^0.2.1", + "@types/yargs": "^16.0.4" + } + }, + "packages/create-flex-plugin/node_modules/@types/yargs": { + "version": "16.0.5", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", + "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "packages/create-flex-plugin/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "packages/create-flex-plugin/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "packages/create-flex-plugin/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "packages/create-flex-plugin/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "license": "MIT" + }, + "packages/create-flex-plugin/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "packages/create-flex-plugin/node_modules/tmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", + "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "license": "MIT", + "dependencies": { + "rimraf": "^3.0.0" + }, + "engines": { + "node": ">=8.17.0" + } + }, + "packages/create-flex-plugin/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "packages/create-flex-plugin/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "license": "MIT", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "packages/flex-dev-utils": { + "name": "@twilio/flex-dev-utils", + "version": "7.1.3", + "license": "MIT", + "dependencies": { + "@k88/pipe-compose": "^2.5.0", + "@segment/analytics-node": "^1.3.0", + "@twilio/flex-plugins-utils-env": "7.1.3", + "@twilio/flex-plugins-utils-exception": "7.1.3", + "address": "^1.1.2", + "adm-zip": "0.5.10", + "app-module-path": "^2.2.0", + "axios": "^1.6.4", + "axios-cache-interceptor": "^1.5.1", + "axios-mock-adapter": "^1.20.0", + "boxen": "^5.1.2", + "chalk": "^4.1.2", + "columnify": "^1.5.4", + "copy-template-dir": "^1.4.0", + "daemonize-process": "^3.0.0", + "execa": "^5.1.1", + "find-in-files": "^0.5.0", + "form-data": "^4.0.0", + "globby": "^11.0.4", + "https-proxy-agent": "^5.0.0", + "inquirer": "7.3.3", + "lodash": "^4.17.21", + "log-symbols": "^4.1.0", + "mkdirp": "^1.0.4", + "net": "^1.0.2", + "open": "^8.2.1", + "ora": "^5.4.1", + "package-json": "^7.0.0", + "qs": "^6.10.3", + "rimraf": "^3.0.2", + "semver": "^7.3.5", + "string-width": "^4.2.3", + "table": "^6.7.3", + "update-notifier": "^5.1.0", + "url": "^0.11.0", + "url-join": "^4.0.1", + "util": "^0.12.4", + "wrap-ansi": "^4.0.0" + }, + "devDependencies": { + "@types/adm-zip": "0.5.5", + "@types/app-module-path": "^2.2.0", + "@types/columnify": "^1.5.1", + "@types/find-in-files": "^0.5.1", + "@types/inquirer": "^7.3.3", + "@types/lodash": "^4.14.177", + "@types/mkdirp": "^1.0.2", + "@types/qs": "^6.9.7", + "@types/rimraf": "^3.0.2", + "@types/semver": "^7.3.8", + "@types/string-width": "^4.0.1", + "@types/table": "^6.3.2", + "@types/update-notifier": "^5.1.0", + "@types/url-join": "^4.0.1", + "@types/wrap-ansi": "^3.0.0", + "axios-mock-adapter": "^1.20.0" + }, + "optionalDependencies": { + "keytar": "^7.7.0" + } + }, + "packages/flex-dev-utils/node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "packages/flex-dev-utils/node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "packages/flex-dev-utils/node_modules/@types/update-notifier": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@types/update-notifier/-/update-notifier-5.1.0.tgz", + "integrity": "sha512-aGY5pH1Q/DcToKXl4MCj1c0uDUB+zSVFDRCI7Q7js5sguzBTqJV/5kJA2awofbtWYF3xnon1TYdZYnFditRPtQ==", + "dev": true, + "dependencies": { + "@types/configstore": "*", + "boxen": "^4.2.0" + } + }, + "packages/flex-dev-utils/node_modules/@types/update-notifier/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "packages/flex-dev-utils/node_modules/@types/update-notifier/node_modules/boxen": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", + "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", + "dev": true, + "dependencies": { + "ansi-align": "^3.0.0", + "camelcase": "^5.3.1", + "chalk": "^3.0.0", + "cli-boxes": "^2.2.0", + "string-width": "^4.1.0", + "term-size": "^2.1.0", + "type-fest": "^0.8.1", + "widest-line": "^3.1.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/flex-dev-utils/node_modules/@types/update-notifier/node_modules/chalk": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", + "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "packages/flex-dev-utils/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "engines": { + "node": ">=4" + } + }, + "packages/flex-dev-utils/node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "packages/flex-dev-utils/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "packages/flex-dev-utils/node_modules/chalk/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "packages/flex-dev-utils/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "packages/flex-dev-utils/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "packages/flex-dev-utils/node_modules/daemonize-process": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/daemonize-process/-/daemonize-process-3.0.0.tgz", + "integrity": "sha512-xydLk6LrHflrLTqcYBnPHtwFnAQR+lhP/OHHef6sQ9E0I0tR42xGV5y2qFd1DVJsUt/2pMQN7OSOVmmX+Cubhw==", + "engines": { + "node": ">=10" + } + }, + "packages/flex-dev-utils/node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/flex-dev-utils/node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "engines": { + "node": ">=10" + } + }, + "packages/flex-dev-utils/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/flex-dev-utils/node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "packages/flex-dev-utils/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==", + "engines": { + "node": ">=8" + } + }, + "packages/flex-dev-utils/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "engines": { + "node": ">=4" + } + }, + "packages/flex-dev-utils/node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "packages/flex-dev-utils/node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "packages/flex-dev-utils/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, + "packages/flex-dev-utils/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/flex-dev-utils/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "packages/flex-dev-utils/node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/flex-dev-utils/node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "engines": { + "node": ">=8" + } + }, + "packages/flex-dev-utils/node_modules/package-json": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-7.0.0.tgz", + "integrity": "sha512-CHJqc94AA8YfSLHGQT3DbvSIuE12NLFekpM4n7LRrAd3dOJtA911+4xe9q6nC3/jcKraq7nNS9VxgtT0KC+diA==", + "dependencies": { + "got": "^11.8.2", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/flex-dev-utils/node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/flex-dev-utils/node_modules/semver": { + "version": "7.3.8", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", + "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "packages/flex-dev-utils/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "packages/flex-dev-utils/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==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "packages/flex-dev-utils/node_modules/wrap-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-4.0.0.tgz", + "integrity": "sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg==", + "dependencies": { + "ansi-styles": "^3.2.0", + "string-width": "^2.1.1", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "packages/flex-dev-utils/node_modules/wrap-ansi/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "packages/flex-plugin": { + "name": "@twilio/flex-plugin", + "version": "7.1.3", + "license": "MIT", + "devDependencies": { + "@twilio/flex-ui": "^2" + } + }, + "packages/flex-plugin-e2e-tests": { + "name": "@twilio/flex-plugin-e2e-tests", + "version": "7.1.3", + "license": "MIT", + "dependencies": { + "@twilio/flex-dev-utils": "7.1.3", + "@twilio/flex-plugins-api-client": "7.1.3", + "axios": "^0.26.1", + "lodash": "4.17.21", + "node-fetch": "^3.3.2", + "package-json": "^7.0.0", + "puppeteer": "^21.3.7", + "replace-in-file": "^6.3.2", + "semver": "^7.3.5" + }, + "devDependencies": { + "@types/lodash": "4.14.177", + "@types/node-fetch": "^2.6.12", + "@types/semver": "^7.3.9" + }, + "engines": { + "node": "^18 || ^20 || ^22 || ^24" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/@szmarczak/http-timer": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", + "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "dependencies": { + "defer-to-connect": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/@types/lodash": { + "version": "4.14.177", + "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.177.tgz", + "integrity": "sha512-0fDwydE2clKe9MNfvXHBHF9WEahRuj+msTuQqOmAApNORFvhMYZKNGGJdCzuhheVjMps/ti0Ak/iJPACMaevvw==", + "dev": true, + "license": "MIT" + }, + "packages/flex-plugin-e2e-tests/node_modules/axios": { + "version": "0.26.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", + "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "license": "MIT", + "dependencies": { + "follow-redirects": "^1.14.8" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "dependencies": { + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/data-uri-to-buffer": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", + "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "engines": { + "node": ">= 12" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "dependencies": { + "mimic-response": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "engines": { + "node": ">=10" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/get-stream": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", + "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/got": { + "version": "11.8.6", + "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", + "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "dependencies": { + "@sindresorhus/is": "^4.0.0", + "@szmarczak/http-timer": "^4.0.5", + "@types/cacheable-request": "^6.0.1", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^5.0.3", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "http2-wrapper": "^1.0.0-beta.5.2", + "lowercase-keys": "^2.0.0", + "p-cancelable": "^2.0.0", + "responselike": "^2.0.0" + }, + "engines": { + "node": ">=10.19.0" + }, + "funding": { + "url": "https://github.com/sindresorhus/got?sponsor=1" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" + }, + "packages/flex-plugin-e2e-tests/node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "engines": { + "node": ">=8" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/node-fetch": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", + "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "dependencies": { + "data-uri-to-buffer": "^4.0.0", + "fetch-blob": "^3.1.4", + "formdata-polyfill": "^4.0.10" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-fetch" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/p-cancelable": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", + "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "engines": { + "node": ">=8" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/package-json": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/package-json/-/package-json-7.0.0.tgz", + "integrity": "sha512-CHJqc94AA8YfSLHGQT3DbvSIuE12NLFekpM4n7LRrAd3dOJtA911+4xe9q6nC3/jcKraq7nNS9VxgtT0KC+diA==", + "dependencies": { + "got": "^11.8.2", + "registry-auth-token": "^4.0.0", + "registry-url": "^5.0.0", + "semver": "^7.3.5" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/responselike": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", + "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "dependencies": { + "lowercase-keys": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/flex-plugin-e2e-tests/node_modules/semver": { + "version": "7.6.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", + "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "packages/flex-plugin-scripts": { + "name": "@twilio/flex-plugin-scripts", + "version": "7.1.3", + "license": "MIT", + "dependencies": { + "@jest/types": "^27.0.0", + "@twilio/flex-dev-utils": "7.1.3", + "@twilio/flex-plugin": "7.1.3", + "@twilio/flex-plugin-test": "7.1.3", + "@twilio/flex-plugin-webpack": "7.1.3", + "@twilio/flex-plugin-webpack5": "7.1.3", + "esm-wallaby": "^3.2.30", + "jest": "^27.0.0", + "prop-types": "^15.7.2", + "querystring": "^0.2.1" + }, + "bin": { + "flex-plugin": "bin/flex-plugin" + }, + "devDependencies": { + "@types/enzyme": "^3.10.10", + "@types/jest": "^27.0.0", + "@types/node": "^14.17.18" + }, + "engines": { + "node": "^18 || ^20 || ^22 || ^24" + } + }, + "packages/flex-plugin-scripts/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "packages/flex-plugin-scripts/node_modules/querystring": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", + "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", + "license": "MIT", + "engines": { + "node": ">=0.4.x" + } + }, + "packages/flex-plugin-test": { + "name": "@twilio/flex-plugin-test", + "version": "7.1.3", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.16.0", + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@twilio/flex-dev-utils": "7.1.3", + "@types/node": "20.11.30", + "babel-jest": "^27.0.0", + "babel-polyfill": "^6.26.0", + "babel-preset-react-app": "^10.0.1", + "cheerio": "1.0.0-rc.12", + "jest": "^27.0.0", + "jest-environment-jsdom": "^27.0.0", + "jest-watch-typeahead": "^0.6.4", + "react": "^16", + "react-app-polyfill": "^1.0.6", + "react-dom": "^16", + "react-test-renderer": "^16" + }, + "devDependencies": { + "@jest/types": "^27.0.0" + }, + "engines": { + "node": "^18 || ^20 || ^22 || ^24" + } + }, + "packages/flex-plugin-test/node_modules/@jest/types": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", + "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + } + }, + "packages/flex-plugin-test/node_modules/@types/node": { + "version": "20.11.30", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", + "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "packages/flex-plugin-test/node_modules/@types/yargs": { + "version": "16.0.9", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", + "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" } }, - "node_modules/write-json-file/node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", + "packages/flex-plugin-test/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/write-json-file/node_modules/make-dir": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", - "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", + "packages/flex-plugin-test/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { - "semver": "^6.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/write-json-file/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "packages/flex-plugin-test/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, - "node_modules/write-pkg": { + "packages/flex-plugin-test/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "packages/flex-plugin-test/node_modules/has-flag": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/write-pkg/-/write-pkg-4.0.0.tgz", - "integrity": "sha512-v2UQ+50TNf2rNHJ8NyWttfm/EJUBWMJcx6ZTYZr6Qp52uuegWw/lBkCtCbnYZEmPRNL61m+u67dAmGxo+HTULA==", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "packages/flex-plugin-test/node_modules/react-dom": { + "version": "16.14.0", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", + "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0", + "object-assign": "^4.1.1", + "prop-types": "^15.6.2", + "scheduler": "^0.19.1" + }, + "peerDependencies": { + "react": "^16.14.0" + } + }, + "packages/flex-plugin-test/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, "license": "MIT", "dependencies": { - "sort-keys": "^2.0.0", - "type-fest": "^0.4.1", - "write-json-file": "^3.2.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, - "node_modules/write-pkg/node_modules/detect-indent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-5.0.0.tgz", - "integrity": "sha512-rlpvsxUtM0PQvy9iZe640/IWwWYyBsTApREbA1pHOpmOUIl9MkP/U4z7vTtg4Oaojvqhxt7sdufnT0EzGaR31g==", - "dev": true, + "packages/flex-plugin-utils-jest": { + "name": "@twilio/flex-plugin-utils-jest", + "version": "7.1.3", "license": "MIT", + "devDependencies": { + "jest-matcher-utils": "^26.6.2" + }, "engines": { - "node": ">=4" + "node": "^18 || ^20 || ^22 || ^24" } }, - "node_modules/write-pkg/node_modules/sort-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-2.0.0.tgz", - "integrity": "sha512-/dPCrG1s3ePpWm6yBbxZq5Be1dXGLyLn9Z791chDC3NFrpkVbWGzkBwPN1knaciexFXgRJ7hzdnwZ4stHSDmjg==", - "dev": true, + "packages/flex-plugin-webpack": { + "name": "@twilio/flex-plugin-webpack", + "version": "7.1.3", "license": "MIT", "dependencies": { - "is-plain-obj": "^1.0.0" + "@babel/core": "^7.23.7", + "@babel/plugin-proposal-private-property-in-object": "^7.21.11", + "@babel/preset-env": "^7.16.4", + "@babel/preset-react": "^7.16.0", + "@k88/cra-webpack-hot-dev-client": "^1.1.0", + "@k88/format-webpack-messages": "^1.1.0", + "@k88/interpolate-html-plugin": "^1.0.5", + "@k88/module-scope-plugin": "^1.1.0", + "@k88/typescript-compile-error-formatter": "^1.0.3", + "@twilio/flex-dev-utils": "7.1.3", + "babel-loader": "^8.3.0", + "babel-plugin-named-asset-import": "^0.3.7", + "babel-preset-react-app": "10.0.1", + "cookie-parser": "1.4.6", + "css-loader": "^5.1.3", + "dotenv": "^10.0.0", + "dotenv-webpack": "^6.0.4", + "fork-ts-checker-webpack-plugin": "^4.1.6", + "html-webpack-plugin": "^4.5.0", + "node-ipc": "9.1.4", + "pnp-webpack-plugin": "^1.7.0", + "postcss": "^8.4.31", + "postcss-flexbugs-fixes": "^5.0.2", + "postcss-loader": "^4.2.0", + "postcss-preset-env": "^9.1.4", + "resolve-url-loader": "^5.0.0", + "sass": "^1.32.8", + "sass-loader": "^10.1.1", + "style-loader": "^2.0.0", + "tapable": "^1.1.3", + "terser-webpack-plugin": "^4.2.3", + "ts-pnp": "^1.2.0", + "url-loader": "^4.1.1", + "webpack": "^4.47.0", + "webpack-dev-server": "^4.15.2" + }, + "devDependencies": { + "@types/cookie-parser": "1.4.7", + "@types/dotenv-webpack": "^6.0.0", + "@types/node-ipc": "9.1.3", + "@types/tapable": "^1.0.8", + "@types/terser-webpack-plugin": "^2.2.1", + "@types/webpack": "^4.41.26", + "express-serve-static-core": "^0.1.1", + "typescript": "^4.9.5" }, "engines": { - "node": ">=4" + "node": "^18 || ^20 || ^22 || ^24" } }, - "node_modules/write-pkg/node_modules/type-fest": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.4.1.tgz", - "integrity": "sha512-IwzA/LSfD2vC1/YDYMv/zHP4rDF1usCwllsDpbolT3D4fUepIO7f9K70jjmUewU/LmGUKJcwcVtDCpnKk4BPMw==", - "dev": true, - "license": "(MIT OR CC0-1.0)", + "packages/flex-plugin-webpack5": { + "name": "@twilio/flex-plugin-webpack5", + "version": "7.1.3", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.22.10", + "@babel/preset-env": "^7.22.10", + "@babel/preset-modules": "^0.1.6", + "@babel/preset-react": "^7.22.5", + "@babel/preset-typescript": "^7.22.11", + "@k88/cra-webpack-hot-dev-client": "^1.1.0", + "@k88/format-webpack-messages": "^1.1.0", + "@k88/interpolate-html-plugin": "^1.0.5", + "@k88/module-scope-plugin": "^1.1.0", + "@twilio/flex-dev-utils": "^7.1.0", + "@types/express-serve-static-core": "^4.17.35", + "babel-loader": "^9.1.3", + "babel-plugin-named-asset-import": "^0.3.8", + "babel-preset-react-app": "^10.0.1", + "css-loader-wp5": "npm:css-loader@^6.8.1", + "dotenv": "^10.0.0", + "dotenv-webpack-wp5": "npm:dotenv-webpack@^8.0.1", + "fork-ts-checker-webpack-plugin": "^9.1.0", + "html-webpack-plugin-wp5": "npm:html-webpack-plugin@^5.5.3", + "lodash": "^4.17.21", + "node-ipc": "9.1.4", + "pnp-webpack-plugin": "^1.7.0", + "postcss": "^8.2.8", + "postcss-flexbugs-fixes": "^5.0.2", + "postcss-loader-wp5": "npm:postcss-loader@^7.3.3", + "postcss-preset-env": "^6.7.0", + "resolve-url-loader": "^4.0.0", + "sass": "^1.32.8", + "sass-loader-wp5": "npm:sass-loader@^13.3.2", + "style-loader-wp5": "npm:style-loader@^3.3.3", + "tapable": "^1.1.3", + "terser-webpack-plugin-wp5": "npm:terser-webpack-plugin@^2.3.8", + "ts-pnp": "^1.2.0", + "url-loader": "^4.1.1", + "webpack": "5.88.2", + "webpack-dev-server-wp5": "npm:webpack-dev-server@^4.15.1", + "webpack5": "npm:webpack@5.88.2" + }, + "devDependencies": { + "@types/dotenv-webpack": "npm:@types/dotenv-webpack@^6.0.0", + "@types/node-ipc": "9.1.3", + "@types/tapable": "^1.0.8", + "@types/terser-webpack-plugin-wp5": "npm:@types/terser-webpack-plugin@^2.2.1", + "express-serve-static-core": "^0.1.1", + "typescript": "^4.9.5" + }, "engines": { - "node": ">=6" + "node": "^18 || ^20 || ^22 || ^24" } }, - "node_modules/write-pkg/node_modules/write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "license": "ISC", + "packages/flex-plugin-webpack5/node_modules/@types/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==", + "license": "MIT" + }, + "packages/flex-plugin-webpack5/node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "license": "MIT", "dependencies": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" } }, - "node_modules/write-pkg/node_modules/write-json-file": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/write-json-file/-/write-json-file-3.2.0.tgz", - "integrity": "sha512-3xZqT7Byc2uORAatYiP3DHUUAVEkNOswEWNs9H5KXiicRTvzYzYqKjYc4G7p+8pltvAw641lVByKVtMpf+4sYQ==", - "dev": true, + "packages/flex-plugin-webpack5/node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "license": "MIT" + }, + "packages/flex-plugin-webpack5/node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "license": "MIT" + }, + "packages/flex-plugin-webpack5/node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "license": "MIT" + }, + "packages/flex-plugin-webpack5/node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", "license": "MIT", "dependencies": { - "detect-indent": "^5.0.0", - "graceful-fs": "^4.1.15", - "make-dir": "^2.1.0", - "pify": "^4.0.1", - "sort-keys": "^2.0.0", - "write-file-atomic": "^2.4.2" + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "packages/flex-plugin-webpack5/node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "packages/flex-plugin-webpack5/node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "packages/flex-plugin-webpack5/node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "license": "MIT" + }, + "packages/flex-plugin-webpack5/node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "packages/flex-plugin-webpack5/node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "packages/flex-plugin-webpack5/node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "packages/flex-plugin-webpack5/node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "packages/flex-plugin-webpack5/node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "packages/flex-plugin-webpack5/node_modules/acorn": { + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.18.0.tgz", + "integrity": "sha512-lGq+9yr1/GuAWaVYIHRjvvySG5/4VfKIvC8EWxStPdcDh/Ka7FG3twP6v4d5BkravUilhIAsG4Qj83t02LWUPQ==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" }, "engines": { - "node": ">=6" + "node": ">=0.4.0" } }, - "node_modules/ws": { - "version": "7.4.6", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", - "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", + "packages/flex-plugin-webpack5/node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", + "deprecated": "package has been renamed to acorn-import-attributes", "license": "MIT", - "engines": { - "node": ">=8.3.0" + "peerDependencies": { + "acorn": "^8" + } + }, + "packages/flex-plugin-webpack5/node_modules/ajv-formats": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz", + "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==", + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" }, "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "ajv": "^8.0.0" }, "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { + "ajv": { "optional": true } } }, - "node_modules/xdg-basedir": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/xdg-basedir/-/xdg-basedir-4.0.0.tgz", - "integrity": "sha512-PSNhEJDejZYV7h50BohL09Er9VaIefr2LMAf3OEmpCkjOi34eYyQYAXUTjEQtZJTKcF0E2UKTh+osDLsgNim9Q==", + "packages/flex-plugin-webpack5/node_modules/ajv-formats/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "packages/flex-plugin-webpack5/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/xml-name-validator": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-3.0.0.tgz", - "integrity": "sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==", - "license": "Apache-2.0" + "packages/flex-plugin-webpack5/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" }, - "node_modules/xmlbuilder": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", - "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==", + "packages/flex-plugin-webpack5/node_modules/autoprefixer": { + "version": "9.8.8", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz", + "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.12.0", + "caniuse-lite": "^1.0.30001109", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "picocolors": "^0.2.1", + "postcss": "^7.0.32", + "postcss-value-parser": "^4.1.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "funding": { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + } + }, + "packages/flex-plugin-webpack5/node_modules/autoprefixer/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, "engines": { - "node": ">=6.0" + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "node_modules/xmlchars": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz", - "integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==", + "packages/flex-plugin-webpack5/node_modules/babel-loader": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz", + "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==", + "license": "MIT", + "dependencies": { + "find-cache-dir": "^4.0.0", + "schema-utils": "^4.0.0" + }, + "engines": { + "node": ">= 14.15.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0", + "webpack": ">=5" + } + }, + "packages/flex-plugin-webpack5/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "packages/flex-plugin-webpack5/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "license": "MIT", + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "packages/flex-plugin-webpack5/node_modules/clean-css": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz", + "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==", + "license": "MIT", + "dependencies": { + "source-map": "~0.6.0" + }, + "engines": { + "node": ">= 10.0" + } + }, + "packages/flex-plugin-webpack5/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "packages/flex-plugin-webpack5/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, - "node_modules/xmlhttprequest": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha512-58Im/U0mlVBLM38NdZjHyhuMtCqa61469k2YP/AaPbvCoV9aQGUpbJBj1QRm2ytRiVQBD/fsw7L2bJGDVQswBA==", - "dev": true, + "packages/flex-plugin-webpack5/node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", "license": "MIT", "engines": { - "node": ">=0.4.0" + "node": ">= 12" } }, - "node_modules/xtend": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", - "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "packages/flex-plugin-webpack5/node_modules/css-blank-pseudo": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-0.1.4.tgz", + "integrity": "sha512-LHz35Hr83dnFeipc7oqFDmsjHdljj3TQtxGGiNWSOsTLIAubSm4TEz8qCaKFpk7idaQ1GfWscF4E6mgpBysA1w==", + "license": "CC0-1.0", + "dependencies": { + "postcss": "^7.0.5" + }, + "bin": { + "css-blank-pseudo": "cli.js" + }, "engines": { - "node": ">=0.4" + "node": ">=6.0.0" } }, - "node_modules/y18n": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.1.tgz", - "integrity": "sha512-wNcy4NvjMYL8gogWWYAO7ZFWFfHcbdbE57tZO8e4cbpj8tfUcwrwqSl3ad8HxpYWCdXcJUCeKKZS62Av1affwQ==" + "packages/flex-plugin-webpack5/node_modules/css-blank-pseudo/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "packages/flex-plugin-webpack5/node_modules/css-has-pseudo": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-0.10.0.tgz", + "integrity": "sha512-Z8hnfsZu4o/kt+AuFzeGpLVhFOGO9mluyHBaA2bA8aCGTwah5sT3WV/fTHH8UNZUytOIImuGPrl/prlb4oX4qQ==", + "license": "CC0-1.0", + "dependencies": { + "postcss": "^7.0.6", + "postcss-selector-parser": "^5.0.0-rc.4" + }, + "bin": { + "css-has-pseudo": "cli.js" + }, + "engines": { + "node": ">=6.0.0" + } }, - "node_modules/yaml": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", - "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "packages/flex-plugin-webpack5/node_modules/css-has-pseudo/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, "engines": { - "node": ">= 6" + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "node_modules/yamljs": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", - "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", - "dev": true, + "packages/flex-plugin-webpack5/node_modules/css-has-pseudo/node_modules/postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", "license": "MIT", "dependencies": { - "argparse": "^1.0.7", - "glob": "^7.0.5" + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "packages/flex-plugin-webpack5/node_modules/css-loader-wp5": { + "name": "css-loader", + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz", + "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==", + "license": "MIT", + "dependencies": { + "icss-utils": "^5.1.0", + "postcss": "^8.4.33", + "postcss-modules-extract-imports": "^3.1.0", + "postcss-modules-local-by-default": "^4.0.5", + "postcss-modules-scope": "^3.2.0", + "postcss-modules-values": "^4.0.0", + "postcss-value-parser": "^4.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } + } + }, + "packages/flex-plugin-webpack5/node_modules/css-prefers-color-scheme": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-3.1.1.tgz", + "integrity": "sha512-MTu6+tMs9S3EUqzmqLXEcgNRbNkkD/TGFvowpeoWJn5Vfq7FMgsmRQs9X5NXAURiOBmOxm/lLjsDNXDE6k9bhg==", + "license": "CC0-1.0", + "dependencies": { + "postcss": "^7.0.5" }, "bin": { - "json2yaml": "bin/json2yaml", - "yaml2json": "bin/yaml2json" + "css-prefers-color-scheme": "cli.js" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/yamljs/node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "dev": true, - "license": "ISC", + "packages/flex-plugin-webpack5/node_modules/css-prefers-color-scheme/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": "*" + "node": ">=6.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "node_modules/yargs": { - "version": "15.4.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", - "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", - "dev": true, + "packages/flex-plugin-webpack5/node_modules/cssdb": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-4.4.0.tgz", + "integrity": "sha512-LsTAR1JPEM9TpGhl/0p3nQecC2LJ0kD8X5YARu1hk/9I1gril5vDtMZyNxcEpxxDj34YNck/ucjuoUd66K03oQ==", + "license": "CC0-1.0" + }, + "packages/flex-plugin-webpack5/node_modules/cssesc": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-2.0.0.tgz", + "integrity": "sha512-MsCAG1z9lPdoO/IUMLSBWBSVxVtJ1395VGIQ+Fc2gNdkQ1hNDnQdw3YhA71WJCBW1vdwA0cAnk/DnW6bqoEUYg==", "license": "MIT", - "dependencies": { - "cliui": "^6.0.0", - "decamelize": "^1.2.0", - "find-up": "^4.1.0", - "get-caller-file": "^2.0.1", - "require-directory": "^2.1.1", - "require-main-filename": "^2.0.0", - "set-blocking": "^2.0.0", - "string-width": "^4.2.0", - "which-module": "^2.0.0", - "y18n": "^4.0.0", - "yargs-parser": "^18.1.2" + "bin": { + "cssesc": "bin/cssesc" }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "node_modules/yargs-parser": { - "version": "18.1.3", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", - "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", - "license": "ISC", + "packages/flex-plugin-webpack5/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "license": "MIT", "dependencies": { - "camelcase": "^5.0.0", - "decamelize": "^1.2.0" + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" }, - "engines": { - "node": ">=6" + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/yarn": { - "version": "1.22.19", - "resolved": "https://registry.npmjs.org/yarn/-/yarn-1.22.19.tgz", - "integrity": "sha512-/0V5q0WbslqnwP91tirOvldvYISzaqhClxzyUKXYxs07yUILIs5jx/k6CFe8bvKSkds5w+eiOqta39Wk3WxdcQ==", - "hasInstallScript": true, + "packages/flex-plugin-webpack5/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "license": "BSD-2-Clause", - "bin": { - "yarn": "bin/yarn.js", - "yarnpkg": "bin/yarn.js" + "dependencies": { + "domelementtype": "^2.2.0" }, "engines": { - "node": ">=4.0.0" + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/yauzl": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", - "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "license": "MIT", + "packages/flex-plugin-webpack5/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "license": "BSD-2-Clause", "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/yjs": { - "version": "13.6.33", - "resolved": "https://registry.npmjs.org/yjs/-/yjs-13.6.33.tgz", - "integrity": "sha512-q/UYvr1gOk4XII+Cu1CW2dINjYqJJFifTzogEaIARznrvX7uOlHsdTEXcnOBMuIsrCGEEKdNxi74kyMLZlKVfw==", - "dev": true, + "packages/flex-plugin-webpack5/node_modules/enhanced-resolve": { + "version": "5.25.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.25.1.tgz", + "integrity": "sha512-nGXts5znJzmWPu+mIE9izCOzdg63oJca2mDzGWWTth7sr4aCToKcoyFVBQwN75Ij5Pf6p510EwkTqViTRzDV+w==", "license": "MIT", - "peer": true, "dependencies": { - "lib0": "^0.2.99" + "graceful-fs": "^4.2.4", + "tapable": "^2.3.3" }, "engines": { - "node": ">=16.0.0", - "npm": ">=8.0.0" + "node": ">=10.13.0" + } + }, + "packages/flex-plugin-webpack5/node_modules/enhanced-resolve/node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "license": "MIT", + "engines": { + "node": ">=6" }, "funding": { - "type": "GitHub Sponsors ❤", - "url": "https://github.com/sponsors/dmonad" + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "packages/flex-plugin-webpack5/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "packages/flex-plugin-webpack5/node_modules/find-cache-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz", + "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==", + "license": "MIT", + "dependencies": { + "common-path-prefix": "^3.0.0", + "pkg-dir": "^7.0.0" + }, "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/zen-observable": { - "version": "0.8.15", - "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", - "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/zen-observable-ts": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.2.5.tgz", - "integrity": "sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==", - "dev": true, + "packages/flex-plugin-webpack5/node_modules/find-up": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz", + "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==", "license": "MIT", "dependencies": { - "zen-observable": "0.8.15" + "locate-path": "^7.1.0", + "path-exists": "^5.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/create-flex-plugin": { - "name": "@twilio/create-flex-plugin", - "version": "7.1.3", + "packages/flex-plugin-webpack5/node_modules/fork-ts-checker-webpack-plugin": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.1.0.tgz", + "integrity": "sha512-mpafl89VFPJmhnJ1ssH+8wmM2b50n+Rew5x42NeI2U78aRWgtkEtGmctp7iT16UjquJTjorEmIfESj3DxdW84Q==", "license": "MIT", "dependencies": { - "@twilio/flex-dev-utils": "7.1.3", - "esm-wallaby": "^3.2.30", - "tmp": "^0.2.1", - "yargs": "^16.2.0" + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^4.0.1", + "cosmiconfig": "^8.2.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" }, - "bin": { - "create-flex-plugin": "bin/create-flex-plugin" + "engines": { + "node": ">=14.21.3" }, - "devDependencies": { - "@twilio/flex-plugin": "7.1.3", - "@twilio/flex-plugin-scripts": "7.1.3", - "@types/tmp": "^0.2.1", - "@types/yargs": "^16.0.4" + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" } }, - "packages/create-flex-plugin/node_modules/@types/yargs": { - "version": "16.0.5", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.5.tgz", - "integrity": "sha512-AxO/ADJOBFJScHbWhq2xAhlWP24rY4aCEG/NFaMvbT3X2MgRsLjhjQwsn0Zi5zn0LG9jUhCCZMeX9Dkuw6k+vQ==", - "dev": true, + "packages/flex-plugin-webpack5/node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "license": "MIT", "dependencies": { - "@types/yargs-parser": "*" + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "packages/create-flex-plugin/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "packages/flex-plugin-webpack5/node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" }, "engines": { - "node": ">=8" + "node": ">= 10.13.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "packages/create-flex-plugin/node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", - "wrap-ansi": "^7.0.0" + "packages/flex-plugin-webpack5/node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "packages/create-flex-plugin/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "packages/flex-plugin-webpack5/node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=7.0.0" + "node": ">=12" } }, - "packages/create-flex-plugin/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "packages/create-flex-plugin/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "packages/flex-plugin-webpack5/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, "engines": { "node": ">=8" } }, - "packages/create-flex-plugin/node_modules/tmp": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz", - "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==", + "packages/flex-plugin-webpack5/node_modules/html-minifier-terser": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz", + "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==", "license": "MIT", "dependencies": { - "rimraf": "^3.0.0" + "camel-case": "^4.1.2", + "clean-css": "^5.2.2", + "commander": "^8.3.0", + "he": "^1.2.0", + "param-case": "^3.0.4", + "relateurl": "^0.2.7", + "terser": "^5.10.0" + }, + "bin": { + "html-minifier-terser": "cli.js" }, "engines": { - "node": ">=8.17.0" + "node": ">=12" } }, - "packages/create-flex-plugin/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "packages/flex-plugin-webpack5/node_modules/html-webpack-plugin-wp5": { + "name": "html-webpack-plugin", + "version": "5.6.8", + "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.8.tgz", + "integrity": "sha512-MZmKQcTnhEh1SPSyMiEytIeDZDUoBZVorNHivQGXMASHf/BSGGOrKa2xQ5bGx3TCe1n109ecCt+cpww7wwWhKA==", "license": "MIT", "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "@types/html-minifier-terser": "^6.0.0", + "html-minifier-terser": "^6.0.2", + "lodash": "^4.17.21", + "pretty-error": "^4.0.0", + "tapable": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=10.13.0" }, "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/html-webpack-plugin" + }, + "peerDependencies": { + "@rspack/core": "0.x || 1.x || 2.x", + "webpack": "^5.20.0" + }, + "peerDependenciesMeta": { + "@rspack/core": { + "optional": true + }, + "webpack": { + "optional": true + } } }, - "packages/create-flex-plugin/node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "packages/flex-plugin-webpack5/node_modules/html-webpack-plugin-wp5/node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", "license": "MIT", - "dependencies": { - "cliui": "^7.0.2", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.0", - "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" - }, "engines": { - "node": ">=10" + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "packages/flex-dev-utils": { - "name": "@twilio/flex-dev-utils", - "version": "7.1.3", + "packages/flex-plugin-webpack5/node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], "license": "MIT", "dependencies": { - "@k88/pipe-compose": "^2.5.0", - "@segment/analytics-node": "^1.3.0", - "@twilio/flex-plugins-utils-env": "7.1.3", - "@twilio/flex-plugins-utils-exception": "7.1.3", - "address": "^1.1.2", - "adm-zip": "0.5.10", - "app-module-path": "^2.2.0", - "axios": "^1.6.4", - "axios-cache-interceptor": "^1.5.1", - "axios-mock-adapter": "^1.20.0", - "boxen": "^5.1.2", - "chalk": "^4.1.2", - "columnify": "^1.5.4", - "copy-template-dir": "^1.4.0", - "daemonize-process": "^3.0.0", - "execa": "^5.1.1", - "find-in-files": "^0.5.0", - "form-data": "^4.0.0", - "globby": "^11.0.4", - "https-proxy-agent": "^5.0.0", - "inquirer": "7.3.3", - "lodash": "^4.17.21", - "log-symbols": "^4.1.0", - "mkdirp": "^1.0.4", - "net": "^1.0.2", - "open": "^8.2.1", - "ora": "^5.4.1", - "package-json": "^7.0.0", - "qs": "^6.10.3", - "rimraf": "^3.0.2", - "semver": "^7.3.5", - "string-width": "^4.2.3", - "table": "^6.7.3", - "update-notifier": "^5.1.0", - "url": "^0.11.0", - "url-join": "^4.0.1", - "util": "^0.12.4", - "wrap-ansi": "^4.0.0" - }, - "devDependencies": { - "@types/adm-zip": "0.5.5", - "@types/app-module-path": "^2.2.0", - "@types/columnify": "^1.5.1", - "@types/find-in-files": "^0.5.1", - "@types/inquirer": "^7.3.3", - "@types/lodash": "^4.14.177", - "@types/mkdirp": "^1.0.2", - "@types/qs": "^6.9.7", - "@types/rimraf": "^3.0.2", - "@types/semver": "^7.3.8", - "@types/string-width": "^4.0.1", - "@types/table": "^6.3.2", - "@types/update-notifier": "^5.1.0", - "@types/url-join": "^4.0.1", - "@types/wrap-ansi": "^3.0.0", - "axios-mock-adapter": "^1.20.0" - }, - "optionalDependencies": { - "keytar": "^7.7.0" + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" } }, - "packages/flex-dev-utils/node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "engines": { - "node": ">=10" + "packages/flex-plugin-webpack5/node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "engines": { + "node": ">= 10.13.0" } }, - "packages/flex-dev-utils/node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "packages/flex-plugin-webpack5/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "license": "MIT", "dependencies": { - "defer-to-connect": "^2.0.0" + "has-flag": "^4.0.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "packages/flex-dev-utils/node_modules/@types/update-notifier": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@types/update-notifier/-/update-notifier-5.1.0.tgz", - "integrity": "sha512-aGY5pH1Q/DcToKXl4MCj1c0uDUB+zSVFDRCI7Q7js5sguzBTqJV/5kJA2awofbtWYF3xnon1TYdZYnFditRPtQ==", - "dev": true, + "packages/flex-plugin-webpack5/node_modules/js-yaml": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/puzrin" + }, + { + "type": "github", + "url": "https://github.com/sponsors/nodeca" + } + ], + "license": "MIT", "dependencies": { - "@types/configstore": "*", - "boxen": "^4.2.0" + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" } }, - "packages/flex-dev-utils/node_modules/@types/update-notifier/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, + "packages/flex-plugin-webpack5/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "license": "MIT" + }, + "packages/flex-plugin-webpack5/node_modules/loader-runner": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz", + "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==", + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=6.11.5" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "packages/flex-dev-utils/node_modules/@types/update-notifier/node_modules/boxen": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-4.2.0.tgz", - "integrity": "sha512-eB4uT9RGzg2odpER62bBwSLvUeGC+WbRjjyyFhGsKnc8wp/m0+hQsMUvUe3H2V0D5vw0nBdO1hCJoZo5mKeuIQ==", - "dev": true, + "packages/flex-plugin-webpack5/node_modules/locate-path": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz", + "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==", + "license": "MIT", "dependencies": { - "ansi-align": "^3.0.0", - "camelcase": "^5.3.1", - "chalk": "^3.0.0", - "cli-boxes": "^2.2.0", - "string-width": "^4.1.0", - "term-size": "^2.1.0", - "type-fest": "^0.8.1", - "widest-line": "^3.1.0" + "p-locate": "^6.0.0" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/flex-dev-utils/node_modules/@types/update-notifier/node_modules/chalk": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", - "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", - "dev": true, + "packages/flex-plugin-webpack5/node_modules/p-limit": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz", + "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==", + "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "yocto-queue": "^1.0.0" }, "engines": { - "node": ">=8" - } - }, - "packages/flex-dev-utils/node_modules/ansi-regex": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", - "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", - "engines": { - "node": ">=4" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/flex-dev-utils/node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "packages/flex-plugin-webpack5/node_modules/p-locate": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz", + "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==", + "license": "MIT", "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" + "p-limit": "^4.0.0" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "packages/flex-plugin-webpack5/node_modules/path-exists": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz", + "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==", + "license": "MIT", "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" } }, - "packages/flex-dev-utils/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "packages/flex-plugin-webpack5/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "license": "ISC" + }, + "packages/flex-plugin-webpack5/node_modules/pkg-dir": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz", + "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==", + "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "find-up": "^6.3.0" }, "engines": { - "node": ">=10" + "node": ">=14.16" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "packages/flex-dev-utils/node_modules/chalk/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "packages/flex-plugin-webpack5/node_modules/postcss-attribute-case-insensitive": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-4.0.2.tgz", + "integrity": "sha512-clkFxk/9pcdb4Vkn0hAHq3YnxBQ2p0CGD1dy24jN+reBck+EWxMbxSUqN4Yj7t0w8csl87K6p0gxBe1utkJsYA==", + "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "postcss": "^7.0.2", + "postcss-selector-parser": "^6.0.2" + } + }, + "packages/flex-plugin-webpack5/node_modules/postcss-attribute-case-insensitive/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": ">=8" + "node": ">=6.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-dev-utils/node_modules/color-convert": { + "packages/flex-plugin-webpack5/node_modules/postcss-color-functional-notation": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-2.0.1.tgz", + "integrity": "sha512-ZBARCypjEDofW4P6IdPVTLhDNXPRn8T2s1zHbZidW6rPaaZvcnCS2soYFIQJrMZSxiePJ2XIYTlcb2ztr/eT2g==", + "license": "CC0-1.0", "dependencies": { - "color-name": "~1.1.4" + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" }, "engines": { - "node": ">=7.0.0" - } - }, - "packages/flex-dev-utils/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "packages/flex-dev-utils/node_modules/daemonize-process": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/daemonize-process/-/daemonize-process-3.0.0.tgz", - "integrity": "sha512-xydLk6LrHflrLTqcYBnPHtwFnAQR+lhP/OHHef6sQ9E0I0tR42xGV5y2qFd1DVJsUt/2pMQN7OSOVmmX+Cubhw==", - "engines": { - "node": ">=10" + "node": ">=6.0.0" } }, - "packages/flex-dev-utils/node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "packages/flex-plugin-webpack5/node_modules/postcss-color-functional-notation/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", "dependencies": { - "mimic-response": "^3.1.0" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": ">=10" + "node": ">=6.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-dev-utils/node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "packages/flex-plugin-webpack5/node_modules/postcss-color-hex-alpha": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-5.0.3.tgz", + "integrity": "sha512-PF4GDel8q3kkreVXKLAGNpHKilXsZ6xuu+mOQMHWHLPNyjiUBOr75sp5ZKJfmv1MCus5/DWUGcK9hm6qHEnXYw==", + "license": "MIT", + "dependencies": { + "postcss": "^7.0.14", + "postcss-values-parser": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=6.0.0" } }, - "packages/flex-dev-utils/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "packages/flex-plugin-webpack5/node_modules/postcss-color-hex-alpha/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", "dependencies": { - "pump": "^3.0.0" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": ">=8" + "node": ">=6.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-dev-utils/node_modules/got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "packages/flex-plugin-webpack5/node_modules/postcss-color-rebeccapurple": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-4.0.1.tgz", + "integrity": "sha512-aAe3OhkS6qJXBbqzvZth2Au4V3KieR5sRQ4ptb2b2O8wgvB3SJBsdG+jsn2BZbbwekDG8nTfcCNKcSfe/lEy8g==", + "license": "MIT", "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" }, "engines": { - "node": ">=10.19.0" - }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" + "node": ">=6.0.0" } }, - "packages/flex-dev-utils/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==", + "packages/flex-plugin-webpack5/node_modules/postcss-color-rebeccapurple/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, "engines": { - "node": ">=8" + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-dev-utils/node_modules/is-fullwidth-code-point": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", - "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "packages/flex-plugin-webpack5/node_modules/postcss-custom-media": { + "version": "7.0.8", + "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-7.0.8.tgz", + "integrity": "sha512-c9s5iX0Ge15o00HKbuRuTqNndsJUbaXdiNsksnVH8H4gdc+zbLzr/UasOwNG6CTDpLFekVY4672eWdiiWu2GUg==", + "license": "MIT", + "dependencies": { + "postcss": "^7.0.14" + }, "engines": { - "node": ">=4" + "node": ">=6.0.0" } }, - "packages/flex-dev-utils/node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, - "packages/flex-dev-utils/node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "packages/flex-plugin-webpack5/node_modules/postcss-custom-media/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", "dependencies": { - "json-buffer": "3.0.1" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-dev-utils/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "packages/flex-plugin-webpack5/node_modules/postcss-custom-properties": { + "version": "8.0.11", + "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-8.0.11.tgz", + "integrity": "sha512-nm+o0eLdYqdnJ5abAJeXp4CEU1c1k+eB2yMCvhgzsds/e0umabFrN6HoTy/8Q4K5ilxERdl/JD1LO5ANoYBeMA==", + "license": "MIT", + "dependencies": { + "postcss": "^7.0.17", + "postcss-values-parser": "^2.0.1" + }, "engines": { - "node": ">=8" + "node": ">=6.0.0" } }, - "packages/flex-dev-utils/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "packages/flex-plugin-webpack5/node_modules/postcss-custom-properties/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, "engines": { - "node": ">=10" + "node": ">=6.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-dev-utils/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "bin": { - "mkdirp": "bin/cmd.js" + "packages/flex-plugin-webpack5/node_modules/postcss-custom-selectors": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-5.1.2.tgz", + "integrity": "sha512-DSGDhqinCqXqlS4R7KGxL1OSycd1lydugJ1ky4iRXPHdBRiozyMHrdu0H3o7qNOCiZwySZTUI5MV0T8QhCLu+w==", + "license": "MIT", + "dependencies": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" }, "engines": { - "node": ">=10" + "node": ">=6.0.0" } }, - "packages/flex-dev-utils/node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "packages/flex-plugin-webpack5/node_modules/postcss-custom-selectors/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, "engines": { - "node": ">=10" + "node": ">=6.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-dev-utils/node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "packages/flex-plugin-webpack5/node_modules/postcss-custom-selectors/node_modules/postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" + }, "engines": { - "node": ">=8" + "node": ">=4" } }, - "packages/flex-dev-utils/node_modules/package-json": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-7.0.0.tgz", - "integrity": "sha512-CHJqc94AA8YfSLHGQT3DbvSIuE12NLFekpM4n7LRrAd3dOJtA911+4xe9q6nC3/jcKraq7nNS9VxgtT0KC+diA==", + "packages/flex-plugin-webpack5/node_modules/postcss-dir-pseudo-class": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-5.0.0.tgz", + "integrity": "sha512-3pm4oq8HYWMZePJY+5ANriPs3P07q+LW6FAdTlkFH2XqDdP4HeeJYMOzn0HYLhRSjBO3fhiqSwwU9xEULSrPgw==", + "license": "CC0-1.0", "dependencies": { - "got": "^11.8.2", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^7.3.5" + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" }, "engines": { - "node": ">=12" + "node": ">=4.0.0" + } + }, + "packages/flex-plugin-webpack5/node_modules/postcss-dir-pseudo-class/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-dev-utils/node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "packages/flex-plugin-webpack5/node_modules/postcss-dir-pseudo-class/node_modules/postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "license": "MIT", "dependencies": { - "lowercase-keys": "^2.0.0" + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=4" } }, - "packages/flex-dev-utils/node_modules/semver": { - "version": "7.3.8", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz", - "integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==", + "packages/flex-plugin-webpack5/node_modules/postcss-double-position-gradients": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-1.0.0.tgz", + "integrity": "sha512-G+nV8EnQq25fOI8CH/B6krEohGWnF5+3A6H/+JEpOncu5dCnkS1QQ6+ct3Jkaepw1NGVqqOZH6lqrm244mCftA==", + "license": "CC0-1.0", "dependencies": { - "lru-cache": "^6.0.0" + "postcss": "^7.0.5", + "postcss-values-parser": "^2.0.0" }, - "bin": { - "semver": "bin/semver.js" + "engines": { + "node": ">=6.0.0" + } + }, + "packages/flex-plugin-webpack5/node_modules/postcss-double-position-gradients/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": ">=10" + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-dev-utils/node_modules/strip-ansi": { + "packages/flex-plugin-webpack5/node_modules/postcss-focus-visible": { "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", - "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-4.0.0.tgz", + "integrity": "sha512-Z5CkWBw0+idJHSV6+Bgf2peDOFf/x4o+vX/pwcNYrWpXFrSfTkQ3JQ1ojrq9yS+upnAlNRHeg8uEwFTgorjI8g==", + "license": "CC0-1.0", "dependencies": { - "ansi-regex": "^3.0.0" + "postcss": "^7.0.2" }, "engines": { - "node": ">=4" + "node": ">=6.0.0" } }, - "packages/flex-dev-utils/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==", + "packages/flex-plugin-webpack5/node_modules/postcss-focus-visible/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": ">=8" + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-dev-utils/node_modules/wrap-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-4.0.0.tgz", - "integrity": "sha512-uMTsj9rDb0/7kk1PbcbCcwvHUxp60fGDB/NNXpVa0Q+ic/e7y5+BwTxKfQ33VYgDppSwi/FBzpetYzo8s6tfbg==", + "packages/flex-plugin-webpack5/node_modules/postcss-focus-within": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-3.0.0.tgz", + "integrity": "sha512-W0APui8jQeBKbCGZudW37EeMCjDeVxKgiYfIIEo8Bdh5SpB9sxds/Iq8SEuzS0Q4YFOlG7EPFulbbxujpkrV2w==", + "license": "CC0-1.0", "dependencies": { - "ansi-styles": "^3.2.0", - "string-width": "^2.1.1", - "strip-ansi": "^4.0.0" + "postcss": "^7.0.2" }, "engines": { - "node": ">=6" + "node": ">=6.0.0" } }, - "packages/flex-dev-utils/node_modules/wrap-ansi/node_modules/string-width": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", - "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "packages/flex-plugin-webpack5/node_modules/postcss-focus-within/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", "dependencies": { - "is-fullwidth-code-point": "^2.0.0", - "strip-ansi": "^4.0.0" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": ">=4" + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-plugin": { - "name": "@twilio/flex-plugin", - "version": "7.1.3", + "packages/flex-plugin-webpack5/node_modules/postcss-font-variant": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-4.0.1.tgz", + "integrity": "sha512-I3ADQSTNtLTTd8uxZhtSOrTCQ9G4qUVKPjHiDk0bV75QSxXjVWiJVJ2VLdspGUi9fbW9BcjKJoRvxAH1pckqmA==", "license": "MIT", - "devDependencies": { - "@twilio/flex-ui": "^2" + "dependencies": { + "postcss": "^7.0.2" } }, - "packages/flex-plugin-e2e-tests": { - "name": "@twilio/flex-plugin-e2e-tests", - "version": "7.1.3", + "packages/flex-plugin-webpack5/node_modules/postcss-font-variant/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", "license": "MIT", "dependencies": { - "@twilio/flex-dev-utils": "7.1.3", - "@twilio/flex-plugins-api-client": "7.1.3", - "axios": "^0.26.1", - "lodash": "4.17.21", - "node-fetch": "^3.3.2", - "package-json": "^7.0.0", - "puppeteer": "^21.3.7", - "replace-in-file": "^6.3.2", - "semver": "^7.3.5" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, - "devDependencies": { - "@types/lodash": "4.14.177", - "@types/node-fetch": "^2.6.12", - "@types/semver": "^7.3.9" + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "packages/flex-plugin-webpack5/node_modules/postcss-gap-properties": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-2.0.0.tgz", + "integrity": "sha512-QZSqDaMgXCHuHTEzMsS2KfVDOq7ZFiknSpkrPJY6jmxbugUPTuSzs/vuE5I3zv0WAS+3vhrlqhijiprnuQfzmg==", + "license": "CC0-1.0", + "dependencies": { + "postcss": "^7.0.2" }, "engines": { - "node": "^18 || ^20 || ^22 || ^24" + "node": ">=6.0.0" } }, - "packages/flex-plugin-e2e-tests/node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "packages/flex-plugin-webpack5/node_modules/postcss-gap-properties/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, "engines": { - "node": ">=10" + "node": ">=6.0.0" }, "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-plugin-e2e-tests/node_modules/@szmarczak/http-timer": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-4.0.6.tgz", - "integrity": "sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==", + "packages/flex-plugin-webpack5/node_modules/postcss-image-set-function": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-3.0.1.tgz", + "integrity": "sha512-oPTcFFip5LZy8Y/whto91L9xdRHCWEMs3e1MdJxhgt4jy2WYXfhkng59fH5qLXSCPN8k4n94p1Czrfe5IOkKUw==", + "license": "CC0-1.0", "dependencies": { - "defer-to-connect": "^2.0.0" + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" }, "engines": { - "node": ">=10" + "node": ">=6.0.0" } }, - "packages/flex-plugin-e2e-tests/node_modules/@types/lodash": { - "version": "4.14.177", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.177.tgz", - "integrity": "sha512-0fDwydE2clKe9MNfvXHBHF9WEahRuj+msTuQqOmAApNORFvhMYZKNGGJdCzuhheVjMps/ti0Ak/iJPACMaevvw==", - "dev": true, - "license": "MIT" - }, - "packages/flex-plugin-e2e-tests/node_modules/axios": { - "version": "0.26.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.26.1.tgz", - "integrity": "sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==", + "packages/flex-plugin-webpack5/node_modules/postcss-image-set-function/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.14.8" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-plugin-e2e-tests/node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "packages/flex-plugin-webpack5/node_modules/postcss-lab-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-2.0.1.tgz", + "integrity": "sha512-whLy1IeZKY+3fYdqQFuDBf8Auw+qFuVnChWjmxm/UhHWqNHZx+B99EwxTvGYmUBqe3Fjxs4L1BoZTJmPu6usVg==", + "license": "CC0-1.0", "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" + "@csstools/convert-colors": "^1.4.0", + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" }, "engines": { - "node": ">=8" + "node": ">=6.0.0" } }, - "packages/flex-plugin-e2e-tests/node_modules/data-uri-to-buffer": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz", - "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==", + "packages/flex-plugin-webpack5/node_modules/postcss-lab-function/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, "engines": { - "node": ">= 12" + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-plugin-e2e-tests/node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "packages/flex-plugin-webpack5/node_modules/postcss-loader-wp5": { + "name": "postcss-loader", + "version": "7.3.4", + "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz", + "integrity": "sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A==", + "license": "MIT", "dependencies": { - "mimic-response": "^3.1.0" + "cosmiconfig": "^8.3.5", + "jiti": "^1.20.0", + "semver": "^7.5.4" }, "engines": { - "node": ">=10" + "node": ">= 14.15.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "postcss": "^7.0.0 || ^8.0.1", + "webpack": "^5.0.0" } }, - "packages/flex-plugin-e2e-tests/node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "packages/flex-plugin-webpack5/node_modules/postcss-loader-wp5/node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, "engines": { - "node": ">=10" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "packages/flex-plugin-e2e-tests/node_modules/get-stream": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", - "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", + "packages/flex-plugin-webpack5/node_modules/postcss-logical": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-3.0.0.tgz", + "integrity": "sha512-1SUKdJc2vuMOmeItqGuNaC+N8MzBWFWEkAnRnLpFYj1tGGa7NqyVBujfRtgNa2gXR+6RkGUiB2O5Vmh7E2RmiA==", + "license": "CC0-1.0", "dependencies": { - "pump": "^3.0.0" + "postcss": "^7.0.2" }, "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6.0.0" } }, - "packages/flex-plugin-e2e-tests/node_modules/got": { - "version": "11.8.6", - "resolved": "https://registry.npmjs.org/got/-/got-11.8.6.tgz", - "integrity": "sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==", + "packages/flex-plugin-webpack5/node_modules/postcss-logical/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", "dependencies": { - "@sindresorhus/is": "^4.0.0", - "@szmarczak/http-timer": "^4.0.5", - "@types/cacheable-request": "^6.0.1", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^5.0.3", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "http2-wrapper": "^1.0.0-beta.5.2", - "lowercase-keys": "^2.0.0", - "p-cancelable": "^2.0.0", - "responselike": "^2.0.0" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": ">=10.19.0" + "node": ">=6.0.0" }, "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-plugin-e2e-tests/node_modules/json-buffer": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", - "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==" - }, - "packages/flex-plugin-e2e-tests/node_modules/keyv": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", - "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "packages/flex-plugin-webpack5/node_modules/postcss-nesting": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-7.0.1.tgz", + "integrity": "sha512-FrorPb0H3nuVq0Sff7W2rnc3SmIcruVC6YwpcS+k687VxyxO33iE1amna7wHuRVzM8vfiYofXSBHNAZ3QhLvYg==", + "license": "CC0-1.0", "dependencies": { - "json-buffer": "3.0.1" - } - }, - "packages/flex-plugin-e2e-tests/node_modules/lowercase-keys": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "postcss": "^7.0.2" + }, "engines": { - "node": ">=8" + "node": ">=6.0.0" } }, - "packages/flex-plugin-e2e-tests/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "packages/flex-plugin-webpack5/node_modules/postcss-nesting/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, "engines": { - "node": ">=10" + "node": ">=6.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-plugin-e2e-tests/node_modules/node-fetch": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz", - "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==", + "packages/flex-plugin-webpack5/node_modules/postcss-overflow-shorthand": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-2.0.0.tgz", + "integrity": "sha512-aK0fHc9CBNx8jbzMYhshZcEv8LtYnBIRYQD5i7w/K/wS9c2+0NSR6B3OVMu5y0hBHYLcMGjfU+dmWYNKH0I85g==", + "license": "CC0-1.0", + "dependencies": { + "postcss": "^7.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "packages/flex-plugin-webpack5/node_modules/postcss-overflow-shorthand/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", "dependencies": { - "data-uri-to-buffer": "^4.0.0", - "fetch-blob": "^3.1.4", - "formdata-polyfill": "^4.0.10" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + "node": ">=6.0.0" }, "funding": { "type": "opencollective", - "url": "https://opencollective.com/node-fetch" + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-plugin-e2e-tests/node_modules/normalize-url": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", - "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "packages/flex-plugin-webpack5/node_modules/postcss-page-break": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-2.0.0.tgz", + "integrity": "sha512-tkpTSrLpfLfD9HvgOlJuigLuk39wVTbbd8RKcy8/ugV2bNBUW3xU+AIqyxhDrQr1VUj1RmyJrBn1YWrqUm9zAQ==", + "license": "MIT", + "dependencies": { + "postcss": "^7.0.2" + } + }, + "packages/flex-plugin-webpack5/node_modules/postcss-page-break/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, "engines": { - "node": ">=10" + "node": ">=6.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-plugin-e2e-tests/node_modules/p-cancelable": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", - "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", + "packages/flex-plugin-webpack5/node_modules/postcss-place": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-4.0.1.tgz", + "integrity": "sha512-Zb6byCSLkgRKLODj/5mQugyuj9bvAAw9LqJJjgwz5cYryGeXfFZfSXoP1UfveccFmeq0b/2xxwcTEVScnqGxBg==", + "license": "CC0-1.0", + "dependencies": { + "postcss": "^7.0.2", + "postcss-values-parser": "^2.0.0" + }, "engines": { - "node": ">=8" + "node": ">=6.0.0" } }, - "packages/flex-plugin-e2e-tests/node_modules/package-json": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/package-json/-/package-json-7.0.0.tgz", - "integrity": "sha512-CHJqc94AA8YfSLHGQT3DbvSIuE12NLFekpM4n7LRrAd3dOJtA911+4xe9q6nC3/jcKraq7nNS9VxgtT0KC+diA==", + "packages/flex-plugin-webpack5/node_modules/postcss-place/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", "dependencies": { - "got": "^11.8.2", - "registry-auth-token": "^4.0.0", - "registry-url": "^5.0.0", - "semver": "^7.3.5" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": ">=12" + "node": ">=6.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "packages/flex-plugin-webpack5/node_modules/postcss-preset-env": { + "version": "6.7.2", + "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-6.7.2.tgz", + "integrity": "sha512-nz+VyUUEB9uAxo5VxI0Gq4E31UjHCG3cUiZW3PzRn7KqkGlAEWuYgb/VLbAitEq7Ooubfix+H2JCm9v+C6hJuw==", + "license": "CC0-1.0", + "dependencies": { + "autoprefixer": "^9.6.1", + "browserslist": "^4.6.4", + "caniuse-lite": "^1.0.30000981", + "css-blank-pseudo": "^0.1.4", + "css-has-pseudo": "^0.10.0", + "css-prefers-color-scheme": "^3.1.1", + "cssdb": "^4.4.0", + "postcss": "^7.0.17", + "postcss-attribute-case-insensitive": "^4.0.1", + "postcss-color-functional-notation": "^2.0.1", + "postcss-color-gray": "^5.0.0", + "postcss-color-hex-alpha": "^5.0.3", + "postcss-color-mod-function": "^3.0.3", + "postcss-color-rebeccapurple": "^4.0.1", + "postcss-custom-media": "^7.0.8", + "postcss-custom-properties": "^8.0.11", + "postcss-custom-selectors": "^5.1.2", + "postcss-dir-pseudo-class": "^5.0.0", + "postcss-double-position-gradients": "^1.0.0", + "postcss-env-function": "^2.0.2", + "postcss-focus-visible": "^4.0.0", + "postcss-focus-within": "^3.0.0", + "postcss-font-variant": "^4.0.0", + "postcss-gap-properties": "^2.0.0", + "postcss-image-set-function": "^3.0.1", + "postcss-initial": "^3.0.0", + "postcss-lab-function": "^2.0.1", + "postcss-logical": "^3.0.0", + "postcss-media-minmax": "^4.0.0", + "postcss-nesting": "^7.0.0", + "postcss-overflow-shorthand": "^2.0.0", + "postcss-page-break": "^2.0.0", + "postcss-place": "^4.0.1", + "postcss-pseudo-class-any-link": "^6.0.0", + "postcss-replace-overflow-wrap": "^3.0.0", + "postcss-selector-matches": "^4.0.0", + "postcss-selector-not": "^4.0.0" + }, + "engines": { + "node": ">=6.0.0" } }, - "packages/flex-plugin-e2e-tests/node_modules/responselike": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", - "integrity": "sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==", + "packages/flex-plugin-webpack5/node_modules/postcss-preset-env/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", "dependencies": { - "lowercase-keys": "^2.0.0" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-plugin-e2e-tests/node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "bin": { - "semver": "bin/semver.js" + "packages/flex-plugin-webpack5/node_modules/postcss-pseudo-class-any-link": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-6.0.0.tgz", + "integrity": "sha512-lgXW9sYJdLqtmw23otOzrtbDXofUdfYzNm4PIpNE322/swES3VU9XlXHeJS46zT2onFO7V1QFdD4Q9LiZj8mew==", + "license": "CC0-1.0", + "dependencies": { + "postcss": "^7.0.2", + "postcss-selector-parser": "^5.0.0-rc.3" }, "engines": { - "node": ">=10" + "node": ">=6.0.0" } }, - "packages/flex-plugin-scripts": { - "name": "@twilio/flex-plugin-scripts", - "version": "7.1.3", + "packages/flex-plugin-webpack5/node_modules/postcss-pseudo-class-any-link/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", "license": "MIT", "dependencies": { - "@jest/types": "^27.0.0", - "@twilio/flex-dev-utils": "7.1.3", - "@twilio/flex-plugin": "7.1.3", - "@twilio/flex-plugin-test": "7.1.3", - "@twilio/flex-plugin-webpack": "7.1.3", - "esm-wallaby": "^3.2.30", - "jest": "^27.0.0", - "prop-types": "^15.7.2", - "querystring": "^0.2.1" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, - "bin": { - "flex-plugin": "bin/flex-plugin" + "engines": { + "node": ">=6.0.0" }, - "devDependencies": { - "@types/enzyme": "^3.10.10", - "@types/jest": "^27.0.0", - "@types/node": "^14.17.18" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "packages/flex-plugin-webpack5/node_modules/postcss-pseudo-class-any-link/node_modules/postcss-selector-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-5.0.0.tgz", + "integrity": "sha512-w+zLE5Jhg6Liz8+rQOWEAwtwkyqpfnmsinXjXg6cY7YIONZZtgvE0v2O0uhQBs0peNomOJwWRKt6JBfTdTd3OQ==", + "license": "MIT", + "dependencies": { + "cssesc": "^2.0.0", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" }, "engines": { - "node": "^18 || ^20 || ^22 || ^24" + "node": ">=4" } }, - "packages/flex-plugin-scripts/node_modules/@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", + "packages/flex-plugin-webpack5/node_modules/postcss-replace-overflow-wrap": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-3.0.0.tgz", + "integrity": "sha512-2T5hcEHArDT6X9+9dVSPQdo7QHzG4XKclFT8rU5TzJPDN7RIRTbO9c4drUISOVemLj03aezStHCR2AIcr8XLpw==", "license": "MIT", "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" + "postcss": "^7.0.2" + } + }, + "packages/flex-plugin-webpack5/node_modules/postcss-replace-overflow-wrap/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "license": "MIT", + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-plugin-scripts/node_modules/querystring": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.1.tgz", - "integrity": "sha512-wkvS7mL/JMugcup3/rMitHmd9ecIGd2lhFhK9N3UUQ450h66d1r3Y9nvXzQAW1Lq+wyx61k/1pfKS5KuKiyEbg==", + "packages/flex-plugin-webpack5/node_modules/postcss-selector-not": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-4.0.1.tgz", + "integrity": "sha512-YolvBgInEK5/79C+bdFMyzqTg6pkYqDbzZIST/PDMqa/o3qtXenD05apBG2jLgT0/BQ77d4U2UK12jWpilqMAQ==", "license": "MIT", - "engines": { - "node": ">=0.4.x" + "dependencies": { + "balanced-match": "^1.0.0", + "postcss": "^7.0.2" } }, - "packages/flex-plugin-test": { - "name": "@twilio/flex-plugin-test", - "version": "7.1.3", + "packages/flex-plugin-webpack5/node_modules/postcss-selector-not/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", "license": "MIT", "dependencies": { - "@babel/core": "^7.16.0", - "@babel/plugin-proposal-private-property-in-object": "^7.21.11", - "@twilio/flex-dev-utils": "7.1.3", - "@types/node": "20.11.30", - "babel-jest": "^27.0.0", - "babel-polyfill": "^6.26.0", - "babel-preset-react-app": "^10.0.1", - "cheerio": "1.0.0-rc.12", - "jest": "^27.0.0", - "jest-environment-jsdom": "^27.0.0", - "jest-watch-typeahead": "^0.6.4", - "react": "^16", - "react-app-polyfill": "^1.0.6", - "react-dom": "^16", - "react-test-renderer": "^16" - }, - "devDependencies": { - "@jest/types": "^27.0.0" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": "^18 || ^20 || ^22 || ^24" + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-plugin-test/node_modules/@jest/types": { - "version": "27.5.1", - "resolved": "https://registry.npmjs.org/@jest/types/-/types-27.5.1.tgz", - "integrity": "sha512-Cx46iJ9QpwQTjIdq5VJu2QTMMs3QlEjI0x1QbBP5W1+nMzyc2XmimiRR/CbX9TO0cPTeUlxWMOu8mslYsJ8DEw==", - "dev": true, + "packages/flex-plugin-webpack5/node_modules/pretty-error": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz", + "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==", "license": "MIT", "dependencies": { - "@types/istanbul-lib-coverage": "^2.0.0", - "@types/istanbul-reports": "^3.0.0", - "@types/node": "*", - "@types/yargs": "^16.0.0", - "chalk": "^4.0.0" - }, + "lodash": "^4.17.20", + "renderkid": "^3.0.0" + } + }, + "packages/flex-plugin-webpack5/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "license": "MIT", "engines": { - "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0" + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" } }, - "packages/flex-plugin-test/node_modules/@types/node": { - "version": "20.11.30", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz", - "integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==", + "packages/flex-plugin-webpack5/node_modules/renderkid": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz", + "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==", "license": "MIT", "dependencies": { - "undici-types": "~5.26.4" + "css-select": "^4.1.3", + "dom-converter": "^0.2.0", + "htmlparser2": "^6.1.0", + "lodash": "^4.17.21", + "strip-ansi": "^6.0.1" } }, - "packages/flex-plugin-test/node_modules/@types/yargs": { - "version": "16.0.9", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-16.0.9.tgz", - "integrity": "sha512-tHhzvkFXZQeTECenFoRljLBYPZJ7jAVxqqtEI0qTLOmuultnFp4I9yKE17vTuhf7BkhCu7I4XuemPgikDVuYqA==", - "dev": true, + "packages/flex-plugin-webpack5/node_modules/resolve-url-loader": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-4.0.0.tgz", + "integrity": "sha512-05VEMczVREcbtT7Bz+C+96eUO5HDNvdthIiMB34t7FcF8ehcu4wC0sSgPUubs3XW2Q3CNLJk/BJrCU9wVRymiA==", "license": "MIT", "dependencies": { - "@types/yargs-parser": "*" + "adjust-sourcemap-loader": "^4.0.0", + "convert-source-map": "^1.7.0", + "loader-utils": "^2.0.0", + "postcss": "^7.0.35", + "source-map": "0.6.1" + }, + "engines": { + "node": ">=8.9" + }, + "peerDependencies": { + "rework": "1.0.1", + "rework-visit": "1.0.0" + }, + "peerDependenciesMeta": { + "rework": { + "optional": true + }, + "rework-visit": { + "optional": true + } } }, - "packages/flex-plugin-test/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, + "packages/flex-plugin-webpack5/node_modules/resolve-url-loader/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" + "picocolors": "^0.2.1", + "source-map": "^0.6.1" }, "engines": { - "node": ">=8" + "node": ">=6.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/postcss/" } }, - "packages/flex-plugin-test/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, + "packages/flex-plugin-webpack5/node_modules/sass-loader-wp5": { + "name": "sass-loader", + "version": "13.3.3", + "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-13.3.3.tgz", + "integrity": "sha512-mt5YN2F1MOZr3d/wBRcZxeFgwgkH44wVc2zohO2YF6JiOMkiXe4BYRZpSu2sO1g71mo/j16txzUhsKZlqjVGzA==", "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "neo-async": "^2.6.2" }, "engines": { - "node": ">=10" + "node": ">= 14.15.0" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "fibers": ">= 3.1.0", + "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0", + "sass": "^1.3.0", + "sass-embedded": "*", + "webpack": "^5.0.0" + }, + "peerDependenciesMeta": { + "fibers": { + "optional": true + }, + "node-sass": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + } } }, - "packages/flex-plugin-test/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, + "packages/flex-plugin-webpack5/node_modules/schema-utils": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.5.0.tgz", + "integrity": "sha512-zJlMCZ0cAR5p/Y4oVpRoqioDMJcGxaXRrQ/4rP4WyR84vc5z/DolXdbvXeDpTwbtocDFr2rhPqHPErDCUtz2kA==", "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "@types/json-schema": "^7.0.15", + "ajv": "^8.20.0", + "ajv-formats": "^3.0.1", + "ajv-keywords": "^5.1.0" }, "engines": { - "node": ">=7.0.0" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" } }, - "packages/flex-plugin-test/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" + "packages/flex-plugin-webpack5/node_modules/schema-utils/node_modules/ajv": { + "version": "8.20.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz", + "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==", + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } }, - "packages/flex-plugin-test/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, + "packages/flex-plugin-webpack5/node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "packages/flex-plugin-webpack5/node_modules/semver": { + "version": "7.8.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.8.5.tgz", + "integrity": "sha512-Y7/KDsb8LjooZpwaqGyulO6DQlksgCncchHGk+sZIY4SBvUocMBEFH5Ur1fI4dV+Jvl0w6cjvucaIi40puRioA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, "engines": { - "node": ">=8" + "node": ">=10" } }, - "packages/flex-plugin-test/node_modules/react-dom": { - "version": "16.14.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.14.0.tgz", - "integrity": "sha512-1gCeQXDLoIqMgqD3IO2Ah9bnf0w9kzhwN5q4FGnHZ67hBm9yePzB5JJAIQCc8x3pFnNlwFq4RidZggNAAkzWWw==", + "packages/flex-plugin-webpack5/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==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "packages/flex-plugin-webpack5/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "license": "MIT", "dependencies": { - "loose-envify": "^1.1.0", - "object-assign": "^4.1.1", - "prop-types": "^15.6.2", - "scheduler": "^0.19.1" + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "packages/flex-plugin-webpack5/node_modules/style-loader-wp5": { + "name": "style-loader", + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-3.3.4.tgz", + "integrity": "sha512-0WqXzrsMTyb8yjZJHDqwmnwRJvhALK9LfRtRc6B4UTWe8AijYLZYZ9thuJTZc2VfQWINADW/j+LiJnfy2RoC1w==", + "license": "MIT", + "engines": { + "node": ">= 12.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" }, "peerDependencies": { - "react": "^16.14.0" + "webpack": "^5.0.0" } }, - "packages/flex-plugin-test/node_modules/supports-color": { + "packages/flex-plugin-webpack5/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, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" @@ -43588,70 +47408,199 @@ "node": ">=8" } }, - "packages/flex-plugin-utils-jest": { - "name": "@twilio/flex-plugin-utils-jest", - "version": "7.1.3", + "packages/flex-plugin-webpack5/node_modules/terser": { + "version": "5.51.2", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.51.2.tgz", + "integrity": "sha512-bWnjSNscmuI+GJze6ZupnHP8G/cTcsJF+bXCeQknk2SHQsgbNJnLrqiH9jZ2W4STPVXH2mDKKRX3iwPhc9Cn/Q==", + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "packages/flex-plugin-webpack5/node_modules/terser-webpack-plugin": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.6.1.tgz", + "integrity": "sha512-201R5j+sJpK8nFWwKVyNfZot8FaJbLZDq5evriVzbV1wDtSXDjRUDRfJzHpAaxFDMEhsZL1QkeqM61wgsS3KaQ==", "license": "MIT", - "devDependencies": { - "jest-matcher-utils": "^26.6.2" + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "terser": "^5.31.1" }, "engines": { - "node": "^18 || ^20 || ^22 || ^24" + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@minify-html/node": { + "optional": true + }, + "@swc/core": { + "optional": true + }, + "@swc/css": { + "optional": true + }, + "@swc/html": { + "optional": true + }, + "clean-css": { + "optional": true + }, + "cssnano": { + "optional": true + }, + "csso": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "html-minifier-terser": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "postcss": { + "optional": true + }, + "uglify-js": { + "optional": true + } } }, - "packages/flex-plugin-webpack": { - "name": "@twilio/flex-plugin-webpack", - "version": "7.1.3", + "packages/flex-plugin-webpack5/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==", + "license": "MIT" + }, + "packages/flex-plugin-webpack5/node_modules/watchpack": { + "version": "2.5.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.2.tgz", + "integrity": "sha512-6i/00NBjP4yGPs+caKSyRfpTF/8Torsu0MOW3mMzIbhgISFder8i7xbqgHlLMwJrdiN8ndBV3UA1/AfzPSr+jg==", "license": "MIT", "dependencies": { - "@babel/core": "^7.23.7", - "@babel/plugin-proposal-private-property-in-object": "^7.21.11", - "@babel/preset-env": "^7.16.4", - "@babel/preset-react": "^7.16.0", - "@k88/cra-webpack-hot-dev-client": "^1.1.0", - "@k88/format-webpack-messages": "^1.1.0", - "@k88/interpolate-html-plugin": "^1.0.5", - "@k88/module-scope-plugin": "^1.1.0", - "@k88/typescript-compile-error-formatter": "^1.0.3", - "@twilio/flex-dev-utils": "7.1.3", - "babel-loader": "^8.3.0", - "babel-plugin-named-asset-import": "^0.3.7", - "babel-preset-react-app": "10.0.1", - "cookie-parser": "1.4.6", - "css-loader": "^5.1.3", - "dotenv": "^10.0.0", - "dotenv-webpack": "^6.0.4", - "fork-ts-checker-webpack-plugin": "^4.1.6", - "html-webpack-plugin": "^4.5.0", - "node-ipc": "9.1.4", - "pnp-webpack-plugin": "^1.7.0", - "postcss": "^8.4.31", - "postcss-flexbugs-fixes": "^5.0.2", - "postcss-loader": "^4.2.0", - "postcss-preset-env": "^9.1.4", - "resolve-url-loader": "^5.0.0", - "sass": "^1.32.8", - "sass-loader": "^10.1.1", - "style-loader": "^2.0.0", - "tapable": "^1.1.3", - "terser-webpack-plugin": "^4.2.3", - "ts-pnp": "^1.2.0", - "url-loader": "^4.1.1", - "webpack": "^4.47.0", - "webpack-dev-server": "^4.15.2" + "graceful-fs": "^4.1.2" }, - "devDependencies": { - "@types/cookie-parser": "1.4.7", - "@types/dotenv-webpack": "^6.0.0", - "@types/node-ipc": "9.1.3", - "@types/tapable": "^1.0.8", - "@types/terser-webpack-plugin": "^2.2.1", - "@types/webpack": "^4.41.26", - "express-serve-static-core": "^0.1.1", - "typescript": "^4.9.5" + "engines": { + "node": ">=10.13.0" + } + }, + "packages/flex-plugin-webpack5/node_modules/webpack": { + "version": "5.88.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.88.2.tgz", + "integrity": "sha512-JmcgNZ1iKj+aiR0OvTYtWQqJwq37Pf683dY9bVORwVbUrDhLhdn/PlO2sHsFHPkj7sHNQF3JwaAkp49V+Sq1tQ==", + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.0", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.14.5", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.9", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.7", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" }, "engines": { - "node": "^18 || ^20 || ^22 || ^24" + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "packages/flex-plugin-webpack5/node_modules/webpack-sources": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.6.0.tgz", + "integrity": "sha512-EIMmPVvNI0CYXyRPp34F2Qk7W37/BZVZIofS6LAUnrNjCVahS+hO4mxwFJDjQjODTGZDtVzLYoN2+1dYkhk9qA==", + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "packages/flex-plugin-webpack5/node_modules/webpack/node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "packages/flex-plugin-webpack5/node_modules/webpack/node_modules/tapable": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz", + "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "packages/flex-plugin-webpack5/node_modules/yocto-queue": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", + "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", + "license": "MIT", + "engines": { + "node": ">=12.20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "packages/flex-plugin/node_modules/@apollo/client": { diff --git a/packages/create-flex-plugin/src/lib/__tests__/create-flex-plugin.test.ts b/packages/create-flex-plugin/src/lib/__tests__/create-flex-plugin.test.ts index f6c3145b6..49505135a 100644 --- a/packages/create-flex-plugin/src/lib/__tests__/create-flex-plugin.test.ts +++ b/packages/create-flex-plugin/src/lib/__tests__/create-flex-plugin.test.ts @@ -150,7 +150,6 @@ describe('create-flex-plugin', () => { const mockTimeTaken = 123; const mockConfig = { accountSid: 'AC123456789', - pluginScriptsVersion: '1.0.0', name: 'TestPlugin', flexSdkVersion: '1.24.0', typescript: true, diff --git a/packages/create-flex-plugin/src/lib/commands.ts b/packages/create-flex-plugin/src/lib/commands.ts index f0e34179f..319183810 100644 --- a/packages/create-flex-plugin/src/lib/commands.ts +++ b/packages/create-flex-plugin/src/lib/commands.ts @@ -46,7 +46,6 @@ export const setupConfiguration = async (config: FlexPluginArguments): Promise { const telemetry = new Telemetry(); const accountSid: string = String(config.accountSid); const properties = { - cliVersion: config.pluginScriptsVersion, + cliVersion: config.flexPluginVersion, command: 'create', xtime: Math.round(timeTaken), pluginName: config.name, diff --git a/packages/create-flex-plugin/src/prints/__tests__/finalMessage.test.ts b/packages/create-flex-plugin/src/prints/__tests__/finalMessage.test.ts index 8e9a98619..1e1964bc5 100644 --- a/packages/create-flex-plugin/src/prints/__tests__/finalMessage.test.ts +++ b/packages/create-flex-plugin/src/prints/__tests__/finalMessage.test.ts @@ -10,7 +10,6 @@ describe('finalMessage', () => { name: 'plugin-final-message', targetDirectory: '/target/directory', flexSdkVersion: '1.2.3-flex-sdk', - pluginScriptsVersion: '1.2.3-plugin-script', flexPluginVersion: '1.2.3-plugin-flex', pluginClassName: 'PluginFinalMessage', pluginNamespace: 'PluginFinalMessage', diff --git a/packages/create-flex-plugin/templates/js2/package.json b/packages/create-flex-plugin/templates/js2/package.json index e05e4210e..d4d344cdc 100644 --- a/packages/create-flex-plugin/templates/js2/package.json +++ b/packages/create-flex-plugin/templates/js2/package.json @@ -14,7 +14,6 @@ "@twilio-paste/icons": "^9.2.0" }, "devDependencies": { - "@twilio/flex-plugin-scripts": "{{pluginScriptsVersion}}", "@twilio/flex-ui": "{{flexSdkVersion}}", "@types/node": "^22", "react-test-renderer": "17.0.2" diff --git a/packages/create-flex-plugin/templates/ts2/package.json b/packages/create-flex-plugin/templates/ts2/package.json index 605f5f26d..4ac16acc2 100644 --- a/packages/create-flex-plugin/templates/ts2/package.json +++ b/packages/create-flex-plugin/templates/ts2/package.json @@ -14,7 +14,6 @@ "@twilio-paste/icons": "^9.2.0" }, "devDependencies": { - "@twilio/flex-plugin-scripts": "{{pluginScriptsVersion}}", "@twilio/flex-ui": "{{flexSdkVersion}}", "@types/node": "^22", "react-test-renderer": "17.0.2", diff --git a/packages/flex-dev-utils/src/__tests__/fs.test.ts b/packages/flex-dev-utils/src/__tests__/fs.test.ts index 795136d84..5153ead08 100644 --- a/packages/flex-dev-utils/src/__tests__/fs.test.ts +++ b/packages/flex-dev-utils/src/__tests__/fs.test.ts @@ -877,7 +877,6 @@ describe('fs', () => { '@twilio/flex-plugin': '', }, devDependencies: { - '@twilio/flex-plugin-scripts': '', 'not-a-valid-package': '', } as any, }); @@ -894,7 +893,6 @@ describe('fs', () => { '@twilio/flex-plugin': '', }, devDependencies: { - '@twilio/flex-plugin-scripts': '', '@twilio/flex-ui': '^1', } as any, }); diff --git a/packages/flex-dev-utils/src/errors/lib/FlexPluginError.ts b/packages/flex-dev-utils/src/errors/lib/FlexPluginError.ts index 602a4722b..78fe2ee28 100644 --- a/packages/flex-dev-utils/src/errors/lib/FlexPluginError.ts +++ b/packages/flex-dev-utils/src/errors/lib/FlexPluginError.ts @@ -27,7 +27,7 @@ export default class FlexPluginError extends TwilioError { const { headline } = logger.coloredStrings; if (this.pkg) { const allDeps = { ...this.pkg.dependencies, ...this.pkg.devDependencies }; - const names = ['@twilio/flex-plugin', '@twilio/flex-plugin-scripts']; + const names = ['@twilio/flex-plugin']; logger.newline(); logger.info(`Your plugin ${this.pkg.name} is using the following versions:`); diff --git a/packages/flex-dev-utils/src/errors/lib/__tests__/FlexPluginError.test.ts b/packages/flex-dev-utils/src/errors/lib/__tests__/FlexPluginError.test.ts index 1fc81468b..a1003a1a9 100644 --- a/packages/flex-dev-utils/src/errors/lib/__tests__/FlexPluginError.test.ts +++ b/packages/flex-dev-utils/src/errors/lib/__tests__/FlexPluginError.test.ts @@ -34,15 +34,13 @@ describe('FlexPluginError', () => { dependencies: { '@twilio/flex-plugin': '2.0.0', }, - devDependencies: { - '@twilio/flex-plugin-scripts': '3.0.0', - }, + devDependencies: {}, }); const err = new FlexPluginError(); err.details(); - expect(logger.info).toHaveBeenCalledTimes(3); + expect(logger.info).toHaveBeenCalledTimes(2); }); it('should not print any details if pkg is not found', () => { diff --git a/packages/flex-dev-utils/src/fs.ts b/packages/flex-dev-utils/src/fs.ts index fd74b08ef..304b9a7e2 100644 --- a/packages/flex-dev-utils/src/fs.ts +++ b/packages/flex-dev-utils/src/fs.ts @@ -30,9 +30,6 @@ export interface AppPackageJson extends PackageJson { dependencies: { '@twilio/flex-plugin': string; }; - devDependencies: { - '@twilio/flex-plugin-scripts': string; - }; } export interface FlexConfigurationPlugin { diff --git a/packages/flex-plugin-e2e-tests/package.json b/packages/flex-plugin-e2e-tests/package.json index 981a7f96e..c4ad59b08 100644 --- a/packages/flex-plugin-e2e-tests/package.json +++ b/packages/flex-plugin-e2e-tests/package.json @@ -50,7 +50,7 @@ "@types/semver": "^7.3.9" }, "engines": { - "node": "^16 || ^18 || ^20 || ^22" + "node": "^18 || ^20 || ^22 || ^24" }, "publishConfig": { "access": "public" diff --git a/packages/flex-plugin-e2e-tests/src/core/parameters.ts b/packages/flex-plugin-e2e-tests/src/core/parameters.ts index 319834ad6..b96862b66 100644 --- a/packages/flex-plugin-e2e-tests/src/core/parameters.ts +++ b/packages/flex-plugin-e2e-tests/src/core/parameters.ts @@ -30,6 +30,7 @@ export interface TestScenario { flexUIVersion?: string; reactVersion?: string; isTS?: boolean; + wp5?: boolean; } export interface TestParams { @@ -123,6 +124,7 @@ export const testParams: TestParams = { scenario: { __hidden: false, packageVersion: process.env.PACKAGE_VERSION as string, + wp5: process.env.WP5 === '1', plugins: [ { name: pluginName, diff --git a/packages/flex-plugin-e2e-tests/src/tests/step002.ts b/packages/flex-plugin-e2e-tests/src/tests/step002.ts index 53ef6a954..a9042066a 100644 --- a/packages/flex-plugin-e2e-tests/src/tests/step002.ts +++ b/packages/flex-plugin-e2e-tests/src/tests/step002.ts @@ -57,7 +57,7 @@ const testSuite: TestSuite = async ({ scenario, config }: TestParams): Promise => // await spawn('npm', ['i'], { cwd: plugin.dir }); assertion.fileExists([plugin.dir, 'node_modules']); - assertion.fileExists([plugin.dir, 'node_modules', '@twilio/flex-plugin-scripts']); + assertion.fileExists([plugin.dir, 'node_modules', '@twilio/flex-plugin']); assertion.jsonFileContains( - [plugin.dir, 'node_modules', '@twilio/flex-plugin-scripts', 'package.json'], + [plugin.dir, 'node_modules', '@twilio/flex-plugin', 'package.json'], 'version', scenario.packageVersion, ); diff --git a/packages/flex-plugin-e2e-tests/src/tests/step005.ts b/packages/flex-plugin-e2e-tests/src/tests/step005.ts index 01142b238..f35625926 100644 --- a/packages/flex-plugin-e2e-tests/src/tests/step005.ts +++ b/packages/flex-plugin-e2e-tests/src/tests/step005.ts @@ -17,7 +17,8 @@ const testSuite: TestSuite = async ({ scenario }: TestParams): Promise => to: plugin.componentText, }); - await spawn('twilio', ['flex:plugins:build', '-l', 'debug'], { cwd: plugin.dir }); + const wp5Flag = scenario.wp5 ? ['--wp5'] : []; + await spawn('twilio', ['flex:plugins:build', '-l', 'debug', ...wp5Flag], { cwd: plugin.dir }); assertion.not.dirIsEmpty([plugin.dir, 'build']); assertion.fileExists([plugin.dir, 'build', `${plugin.name}.js`]); diff --git a/packages/flex-plugin-e2e-tests/src/tests/step006.ts b/packages/flex-plugin-e2e-tests/src/tests/step006.ts index 0e5ba7856..851d29026 100644 --- a/packages/flex-plugin-e2e-tests/src/tests/step006.ts +++ b/packages/flex-plugin-e2e-tests/src/tests/step006.ts @@ -11,7 +11,8 @@ const testSuite: TestSuite = async ({ scenario, config, secrets, environment }: const ext = scenario.isTS ? 'tsx' : 'jsx'; const tmpComponentText = 'hot reload works'; - const twilioCliResult = await spawn('twilio', ['flex:plugins:start', '-l', 'debug'], { + const wp5Flag = scenario.wp5 ? ['--wp5'] : []; + const twilioCliResult = await spawn('twilio', ['flex:plugins:start', '-l', 'debug', ...wp5Flag], { detached: true, cwd: plugin.dir, }); diff --git a/packages/flex-plugin-e2e-tests/src/tests/step011.ts b/packages/flex-plugin-e2e-tests/src/tests/step011.ts index 52de4652d..22aa078be 100644 --- a/packages/flex-plugin-e2e-tests/src/tests/step011.ts +++ b/packages/flex-plugin-e2e-tests/src/tests/step011.ts @@ -20,9 +20,10 @@ const testSuite: TestSuite = async ({ scenario, config, secrets, environment }: pluginHelper.waitForPluginToStart(url, testParams.config.start.timeout, testParams.config.start.pollInterval); // Start all 3 plugins (Note: cwd is plugin3 in this scenario since plugin is the remote one) + const wp5Flag = scenario.wp5 ? ['--wp5'] : []; const twilioCliResult = await spawn( 'twilio', - ['flex:plugins:start', '--name', `${plugin1.name}@${plugin1.version}`, '--name', plugin2.name], + ['flex:plugins:start', '--name', `${plugin1.name}@${plugin1.version}`, '--name', plugin2.name, ...wp5Flag], { detached: true, cwd: plugin3.dir }, ); await Promise.all([startPlugin(plugin2.localhostUrl), startPlugin(plugin3.localhostUrl)]); diff --git a/packages/flex-plugin-e2e-tests/src/tests/step012.ts b/packages/flex-plugin-e2e-tests/src/tests/step012.ts index 4b8c16088..10de1d8d9 100644 --- a/packages/flex-plugin-e2e-tests/src/tests/step012.ts +++ b/packages/flex-plugin-e2e-tests/src/tests/step012.ts @@ -41,7 +41,8 @@ const testSuite: TestSuite = async ({ scenario, config, secrets, environment }: ]); // Start 1 local plugin and all remote plugins (note: local is plugin3 by cwd) - const twilioCliResult = await spawn('twilio', ['flex:plugins:start --include-remote'], { + const wp5Flag = scenario.wp5 ? ' --wp5' : ''; + const twilioCliResult = await spawn('twilio', [`flex:plugins:start --include-remote${wp5Flag}`], { detached: true, cwd: plugin3.dir, }); diff --git a/packages/flex-plugin-e2e-tests/src/tests/step013.ts b/packages/flex-plugin-e2e-tests/src/tests/step013.ts index 027248dde..6e8c3bcac 100644 --- a/packages/flex-plugin-e2e-tests/src/tests/step013.ts +++ b/packages/flex-plugin-e2e-tests/src/tests/step013.ts @@ -48,7 +48,7 @@ const testSuite: TestSuite = async ({ scenario, config, secrets, environment }: ]); // Start the 2 local plugins and 1 versioned plugin (Note: cwd is plugin3 in this scenario since plugin is the remote one) - const flags = ['--name', `${plugin1.name}@${oldVersion}`, '--name', plugin2.name]; + const flags = ['--name', `${plugin1.name}@${oldVersion}`, '--name', plugin2.name, ...(scenario.wp5 ? ['--wp5'] : [])]; const twilioCliResult = await spawn('twilio', ['flex:plugins:start', '-l', 'debug', ...flags], { detached: true, cwd: plugin3.dir, diff --git a/packages/flex-plugin-scripts/dev_assets/index.html b/packages/flex-plugin-scripts/dev_assets/index.html index 5e741d489..a84ede8a8 100644 --- a/packages/flex-plugin-scripts/dev_assets/index.html +++ b/packages/flex-plugin-scripts/dev_assets/index.html @@ -15,7 +15,9 @@ + %__FPB_JS_SCRIPTS% + diff --git a/packages/flex-plugin-scripts/package.json b/packages/flex-plugin-scripts/package.json index 45b869b9a..9898e9f20 100644 --- a/packages/flex-plugin-scripts/package.json +++ b/packages/flex-plugin-scripts/package.json @@ -44,6 +44,7 @@ "@twilio/flex-plugin": "7.1.3", "@twilio/flex-plugin-test": "7.1.3", "@twilio/flex-plugin-webpack": "7.1.3", + "@twilio/flex-plugin-webpack5": "7.1.3", "esm-wallaby": "^3.2.30", "jest": "^27.0.0", "prop-types": "^15.7.2", @@ -55,7 +56,7 @@ "@types/node": "^14.17.18" }, "engines": { - "node": "^16 || ^18 || ^20 || ^22" + "node": "^18 || ^20 || ^22 || ^24" }, "publishConfig": { "access": "public" diff --git a/packages/flex-plugin-scripts/src/clients/__tests__/builds.test.ts b/packages/flex-plugin-scripts/src/clients/__tests__/builds.test.ts index 07c60eb9f..ee26c676d 100644 --- a/packages/flex-plugin-scripts/src/clients/__tests__/builds.test.ts +++ b/packages/flex-plugin-scripts/src/clients/__tests__/builds.test.ts @@ -58,7 +58,6 @@ describe('BuildClient', () => { expect(create).toHaveBeenCalledTimes(1); // @ts-ignore expect(create).toHaveBeenCalledWith(buildData); - expect(buildData.Runtime).toEqual('node22'); expect(get).toHaveBeenCalledTimes(1); expect(get).toHaveBeenCalledWith(deployedBuild.sid); diff --git a/packages/flex-plugin-scripts/src/clients/builds.ts b/packages/flex-plugin-scripts/src/clients/builds.ts index 20b35152d..67d514f22 100644 --- a/packages/flex-plugin-scripts/src/clients/builds.ts +++ b/packages/flex-plugin-scripts/src/clients/builds.ts @@ -41,7 +41,7 @@ export default class BuildClient { * Pin the Serverless build runtime rather than tracking 'latest'; a new default Node * version rolling out on the Runtime side must not change how plugins are deployed. */ - private static NodeEngine = 'node22'; + private static NodeEngine = 'latest'; private static timeoutMsec: number = 60_000; diff --git a/packages/flex-plugin-scripts/src/config/index.ts b/packages/flex-plugin-scripts/src/config/index.ts index 20a729bec..c9e6348ab 100644 --- a/packages/flex-plugin-scripts/src/config/index.ts +++ b/packages/flex-plugin-scripts/src/config/index.ts @@ -10,6 +10,14 @@ import { WebpackDevConfigurations, emitDevServerCrashed, } from '@twilio/flex-plugin-webpack'; +import { + webpackFactoryWp5, + webpackDevFactoryWp5, + WebpackTypeWp5, + WebpackConfigurationsWp5, + WebpackDevConfigurationsWp5, + emitDevServerCrashedWp5, +} from '@twilio/flex-plugin-webpack5'; import jestFactory, { JestConfigurations } from './jest.config'; @@ -28,6 +36,14 @@ interface Configurations { jest: JestConfigurations; } +interface ConfigurationsWp5 { + webpackInternal: WebpackConfigurationsWp5; + devServerInternal: WebpackDevConfigurationsWp5; + webpack: WebpackConfigurationsWp5; + devServer: WebpackDevConfigurationsWp5; + jest: JestConfigurations; +} + /** * Returns the configuration; if customer has provided a webpack.config.js, then the generated * config is passed to their Function for modification @@ -99,4 +115,68 @@ const getConfiguration = async ( throw new FlexPluginError('Unsupported configuration name'); }; +export const getConfigurationForWp5 = async ( + name: T, + env: Environment, + emitErrors: boolean, + type: WebpackTypeWp5 = WebpackTypeWp5.Complete, +): Promise => { + const args = { + isProd: env === Environment.Production, + isDev: env === Environment.Development, + isTest: env === Environment.Test, + }; + + if (name === ConfigurationType.Webpack) { + const config = webpackFactoryWp5(env, type); + if (type === WebpackTypeWp5.Static) { + return config as ConfigurationsWp5[T]; + } + + if (checkFilesExist(getPaths().app.webpackConfigPath)) { + try { + return require(getPaths().app.webpackConfigPath)(config, args); + } catch (exception) { + if (emitErrors) { + await emitDevServerCrashedWp5(exception); + } else { + throw exception; + } + } + } + + return config as ConfigurationsWp5[T]; + } + + if (name === ConfigurationType.DevServer) { + const config = webpackDevFactoryWp5(type); + + if (type === WebpackTypeWp5.Static) { + return config as ConfigurationsWp5[T]; + } + + if (checkFilesExist(getPaths().app.devServerConfigPath)) { + try { + return require(getPaths().app.devServerConfigPath)(config, args); + } catch (exception) { + await emitDevServerCrashedWp5(exception); + } + } + + return config as ConfigurationsWp5[T]; + } + + if (name === ConfigurationType.Jest) { + const config = jestFactory(); + + if (checkFilesExist(getPaths().app.jestConfigPath)) { + return require(getPaths().app.jestConfigPath)(config, args); + } + + return config as ConfigurationsWp5[T]; + } + + throw new FlexPluginError('Unsupported configuration name'); +}; + export default getConfiguration; diff --git a/packages/flex-plugin-scripts/src/scripts/__tests__/build.test.ts b/packages/flex-plugin-scripts/src/scripts/__tests__/build.test.ts index fbfb1fc20..9a9b6ca75 100644 --- a/packages/flex-plugin-scripts/src/scripts/__tests__/build.test.ts +++ b/packages/flex-plugin-scripts/src/scripts/__tests__/build.test.ts @@ -1,7 +1,10 @@ import env, { Environment } from '@twilio/flex-dev-utils/dist/env'; import * as fs from '@twilio/flex-dev-utils/dist/fs'; +import { webpack } from '@twilio/flex-plugin-webpack'; +import { webpack5 } from '@twilio/flex-plugin-webpack5'; import * as buildScript from '../build'; +import * as configScripts from '../../config'; import * as prints from '../../prints'; jest.mock('@twilio/flex-dev-utils/dist/logger/lib/logger'); @@ -9,6 +12,14 @@ jest.mock('@twilio/flex-dev-utils/dist/env'); jest.mock('../../prints/buildSuccessful'); jest.mock('../../prints/buildFailure'); jest.mock('../../prints/fileTooLarge'); +jest.mock('@twilio/flex-plugin-webpack', () => ({ + ...jest.requireActual('@twilio/flex-plugin-webpack'), + webpack: jest.fn(), +})); +jest.mock('@twilio/flex-plugin-webpack5', () => ({ + ...jest.requireActual('@twilio/flex-plugin-webpack5'), + webpack5: jest.fn(), +})); describe('BuildScript', () => { const paths = { @@ -108,6 +119,25 @@ describe('BuildScript', () => { _getBundle.mockRestore(); }); + it('should build with webpack 5 when --wp5 is passed', async () => { + jest.spyOn(fs, 'getFileSizeInMB').mockReturnValue(1); + const _runWebpack = jest.spyOn(buildScript, '_runWebpack'); + const _runWebpack5 = jest + .spyOn(buildScript, '_runWebpack5') + .mockResolvedValue({ warnings: [], bundles: [bundle] }); + + await buildScript.default('--wp5'); + + expect(_runWebpack5).toHaveBeenCalledTimes(1); + expect(_runWebpack).not.toHaveBeenCalled(); + expect(prints.buildSuccessful).toHaveBeenCalledTimes(1); + expect(prints.buildSuccessful).toHaveBeenCalledWith([bundle], []); + expect(exit).not.toHaveBeenCalled(); + + _runWebpack.mockRestore(); + _runWebpack5.mockRestore(); + }); + it('should fail to build', async () => { const _getBundle = jest.spyOn(buildScript, '_runWebpack').mockRejectedValue(errorMsg); @@ -175,4 +205,121 @@ describe('BuildScript', () => { }); }); }); + describe('_flattenAssetsWp5', () => { + it('should return assets unchanged when there are no related assets', () => { + const assets = [bundle, { name: 'other', size: 1 }]; + + expect(buildScript._flattenAssetsWp5(assets)).toEqual(assets); + }); + + it('should hoist related assets after their parent', () => { + const sourceMap = { name: 'test-bundle.js.map', size: 1 }; + const other = { name: 'other', size: 2 }; + const assets = [{ ...bundle, related: [sourceMap] }, other]; + + expect(buildScript._flattenAssetsWp5(assets)).toEqual([assets[0], sourceMap, other]); + }); + }); + + describe('_handlerWp5', () => { + const resolve = jest.fn(); + const reject = jest.fn(); + + it('should reject on webpack error', async () => { + const err = new Error('foo'); + await buildScript._handlerWp5(resolve, reject)(err, null); + + expect(reject).toHaveBeenCalledTimes(1); + expect(reject).toHaveBeenCalledWith(err); + expect(resolve).not.toHaveBeenCalled(); + }); + + it('should reject with the error messages on compile error', async () => { + const toJson = jest.fn().mockReturnValue({ errors: [{ message: errorMsg }] }); + const stats = { + toJson, + hasErrors: () => true, + }; + + await buildScript._handlerWp5(resolve, reject)(null, stats); + + expect(toJson).toHaveBeenCalledTimes(1); + expect(reject).toHaveBeenCalledTimes(1); + expect(reject).toHaveBeenCalledWith([errorMsg]); + expect(resolve).not.toHaveBeenCalled(); + }); + + it('should compile successfully and flatten related assets', async () => { + const sourceMap = { name: 'test-bundle.js.map', size: 1 }; + const asset = { ...bundle, related: [sourceMap] }; + const toJson = jest.fn().mockReturnValue({ + assets: [asset], + warnings: [{ message: 'a-warning' }], + }); + const stats = { + toJson, + hasErrors: () => false, + }; + + await buildScript._handlerWp5(resolve, reject)(null, stats); + + expect(toJson).toHaveBeenCalledTimes(2); + expect(reject).not.toHaveBeenCalled(); + expect(resolve).toHaveBeenCalledTimes(1); + expect(resolve).toHaveBeenCalledWith({ + bundles: [asset, sourceMap], + warnings: ['a-warning'], + }); + }); + }); + + describe('_runWebpack', () => { + // Built per test: the top-level beforeEach resets every mock, including toJson + const getStats = () => ({ + toJson: jest.fn().mockReturnValue({ assets: [bundle], warnings: [] }), + hasErrors: () => false, + }); + + it('should run webpack with the production configuration', async () => { + const config = {}; + const getConfiguration = jest.spyOn(configScripts, 'default').mockResolvedValue(config); + const stats = getStats(); + const run = jest.fn((cb) => cb(null, stats)); + (webpack as unknown as jest.Mock).mockReturnValue({ run }); + + const result = await buildScript._runWebpack(); + + expect(getConfiguration).toHaveBeenCalledWith( + configScripts.ConfigurationType.Webpack, + Environment.Production, + false, + ); + expect(webpack).toHaveBeenCalledWith(config); + expect(run).toHaveBeenCalledTimes(1); + expect(result).toEqual({ bundles: [bundle], warnings: [] }); + + getConfiguration.mockRestore(); + }); + + it('should run webpack 5 with the production configuration', async () => { + const config = {}; + const getConfigurationForWp5 = jest.spyOn(configScripts, 'getConfigurationForWp5').mockResolvedValue(config); + const stats = getStats(); + const run = jest.fn((cb) => cb(null, stats)); + (webpack5 as unknown as jest.Mock).mockReturnValue({ run }); + + const result = await buildScript._runWebpack5(); + + expect(getConfigurationForWp5).toHaveBeenCalledWith( + configScripts.ConfigurationType.Webpack, + Environment.Production, + false, + ); + expect(webpack5).toHaveBeenCalledWith(config); + expect(run).toHaveBeenCalledTimes(1); + expect(result).toEqual({ bundles: [bundle], warnings: [] }); + + getConfigurationForWp5.mockRestore(); + }); + }); }); diff --git a/packages/flex-plugin-scripts/src/scripts/__tests__/start.test.ts b/packages/flex-plugin-scripts/src/scripts/__tests__/start.test.ts index 55273fb35..abe5357aa 100644 --- a/packages/flex-plugin-scripts/src/scripts/__tests__/start.test.ts +++ b/packages/flex-plugin-scripts/src/scripts/__tests__/start.test.ts @@ -7,6 +7,11 @@ import * as devServerScripts from '@twilio/flex-plugin-webpack/dist/devServer/we import * as ipcServerScripts from '@twilio/flex-plugin-webpack/dist/devServer/ipcServer'; import * as compilerScripts from '@twilio/flex-plugin-webpack/dist/compiler'; import { PluginsConfig } from '@twilio/flex-plugin-webpack'; +import * as pluginServerScriptsWp5 from '@twilio/flex-plugin-webpack5/dist/devServer/pluginServer'; +import * as devServerScriptsWp5 from '@twilio/flex-plugin-webpack5/dist/devServer/webpackDevServer'; +import * as ipcServerScriptsWp5 from '@twilio/flex-plugin-webpack5/dist/devServer/ipcServer'; +import * as compilerScriptsWp5 from '@twilio/flex-plugin-webpack5/dist/compiler'; +import { PluginsConfigWp5, WebpackTypeWp5 } from '@twilio/flex-plugin-webpack5'; import * as parserUtils from '../../utils/parser'; import * as startScripts from '../start'; @@ -189,7 +194,7 @@ describe('StartScript', () => { * _startDevServer passes this value on to pluginServer and * webpackDevServer, where expect.anything() rejects undefined. */ - getConfiguration.mockReturnValue({} as never); + getConfiguration.mockResolvedValue({} as never); getLocalAndNetworkUrls.mockReturnValue({ local: url, network: url }); compiler.mockReturnThis(); compilerRenderer.mockReturnValue({ onCompile: defaultOnCompile, onRemotePlugins }); @@ -382,4 +387,260 @@ describe('StartScript', () => { expect(config).toEqual(obj); }); }); + describe('default with --wp5', () => { + const port = 1234; + const findPort = jest.spyOn(urlScripts, 'findPort'); + const getDefaultPort = jest.spyOn(urlScripts, 'getDefaultPort'); + const _startDevServer = jest.spyOn(startScripts, '_startDevServer'); + const _startDevServerWp5 = jest.spyOn(startScripts, '_startDevServerWp5'); + const parseUserInputPlugins = jest.spyOn(parserUtils, 'parseUserInputPlugins'); + const _getPluginsConfiguration = jest.spyOn(startScripts, '_getPluginsConfiguration'); + const _getPluginsConfigurationWp5 = jest.spyOn(startScripts, '_getPluginsConfigurationWp5'); + const setCwd = jest.spyOn(fs, 'setCwd'); + const readPluginsJson = jest.spyOn(fs, 'readPluginsJson'); + + beforeEach(() => { + findPort.mockResolvedValue(port); + getDefaultPort.mockReturnValue(port); + _startDevServer.mockReturnThis(); + _startDevServerWp5.mockReturnThis(); + setCwd.mockReturnThis(); + readPluginsJson.mockReturnValue({ plugins: [{ name: pluginName, dir: 'test-dir' }] }); + parseUserInputPlugins.mockReturnValue([{ name: pluginName, remote: false }]); + process.env.PORT = port.toString(); + }); + + afterAll(() => { + findPort.mockRestore(); + getDefaultPort.mockRestore(); + _startDevServer.mockRestore(); + _startDevServerWp5.mockRestore(); + parseUserInputPlugins.mockRestore(); + _getPluginsConfiguration.mockRestore(); + _getPluginsConfigurationWp5.mockRestore(); + setCwd.mockRestore(); + readPluginsJson.mockRestore(); + }); + + it('should start the webpack 5 dev-server with the wp5 plugins configuration', async () => { + _getPluginsConfigurationWp5.mockReturnValue({ [pluginName]: { port } }); + + await startScripts.default(...['--wp5']); + + expect(_startDevServer).not.toHaveBeenCalled(); + expect(_getPluginsConfiguration).not.toHaveBeenCalled(); + expect(_getPluginsConfigurationWp5).toHaveBeenCalledTimes(1); + expect(_startDevServerWp5).toHaveBeenCalledTimes(1); + expect(_startDevServerWp5).toHaveBeenCalledWith( + [{ name: pluginName, remote: false }], + expect.objectContaining({ port, type: WebpackTypeWp5.Complete, remoteAll: false }), + { [pluginName]: { port } }, + ); + }); + + it('should start a webpack 5 plugin without parsing a plugins configuration', async () => { + await startScripts.default(...['plugin', '--name', pluginName, '--wp5']); + + expect(_getPluginsConfiguration).not.toHaveBeenCalled(); + expect(_getPluginsConfigurationWp5).not.toHaveBeenCalled(); + expect(_startDevServerWp5).toHaveBeenCalledTimes(1); + expect(_startDevServerWp5).toHaveBeenCalledWith( + [{ name: pluginName, remote: false }], + expect.objectContaining({ port, type: WebpackTypeWp5.JavaScript, remoteAll: false }), + {}, + ); + }); + + it('should rethrow unhandled rejections and ignore ECONNRESET for start flex', async () => { + _getPluginsConfigurationWp5.mockReturnValue({}); + const handlers: Record void> = {}; + const on = jest.spyOn(process, 'on').mockImplementation((event, handler) => { + handlers[event as string] = handler as (err: Error) => void; + return process; + }); + + await startScripts.default(...['flex', '--wp5']); + + const err = new Error('boom'); + expect(() => handlers.unhandledRejection(err)).toThrow(err); + expect(() => handlers.uncaughtException(err)).toThrow(err); + const reset = Object.assign(new Error('reset'), { code: 'ECONNRESET' }); + expect(() => handlers.uncaughtException(reset)).not.toThrow(); + + on.mockRestore(); + }); + }); + + describe('_startDevServerWp5', () => { + const plugin = { + name: 'plugin-name', + remote: true, + }; + const pluginVersion = { + name: 'plugin-name', + remote: true, + version: '1.0.0', + }; + const opts = { + port: 1234, + remoteAll: true, + }; + const pluginsConfig = { + 'plugin-name': { port: 1234 }, + }; + + const defaultOnCompile = jest.fn(); + const onRemotePlugins = jest.fn(); + const getConfigurationForWp5 = jest.spyOn(configScripts, 'getConfigurationForWp5'); + const compiler = jest.spyOn(compilerScriptsWp5, 'default'); + const compilerRenderer = jest.spyOn(compilerScriptsWp5, 'compilerRenderer'); + const webpackDevServer = jest.spyOn(devServerScriptsWp5, 'default'); + const startIPCServer = jest.spyOn(ipcServerScriptsWp5, 'startIPCServer'); + const startIPCClient = jest.spyOn(ipcServerScriptsWp5, 'startIPCClient'); + const onIPCServerMessage = jest.spyOn(ipcServerScriptsWp5, 'onIPCServerMessage'); + const emitCompileComplete = jest.spyOn(ipcServerScriptsWp5, 'emitCompileComplete'); + const emitDevServerCrashed = jest.spyOn(ipcServerScriptsWp5, 'emitDevServerCrashed'); + const pluginServer = jest.spyOn(pluginServerScriptsWp5, 'default'); + + beforeEach(() => { + getConfigurationForWp5.mockResolvedValue({ plugins: [] }); + compiler.mockReturnThis(); + compilerRenderer.mockReturnValue({ onCompile: defaultOnCompile, onRemotePlugins }); + webpackDevServer.mockReturnThis(); + startIPCServer.mockReturnThis(); + startIPCClient.mockReturnThis(); + onIPCServerMessage.mockReturnThis(); + emitDevServerCrashed.mockResolvedValue(undefined); + pluginServer.mockReturnThis(); + }); + + it('should start pluginServer with remote and versioned plugins', async () => { + await startScripts._startDevServerWp5([plugin], { ...opts, type: WebpackTypeWp5.Complete }, pluginsConfig); + expect(pluginServer).toHaveBeenCalledTimes(1); + expect(pluginServer).toHaveBeenCalledWith( + { local: [], remote: [plugin.name], versioned: [] }, + expect.anything(), + { port: opts.port, remoteAll: opts.remoteAll }, + onRemotePlugins, + pluginsConfig, + ); + + pluginServer.mockReset(); + await startScripts._startDevServerWp5([pluginVersion], { ...opts, type: WebpackTypeWp5.Complete }, pluginsConfig); + expect(pluginServer).toHaveBeenCalledWith( + { local: [], remote: [], versioned: [`${pluginVersion.name}@${pluginVersion.version}`] }, + expect.anything(), + expect.anything(), + onRemotePlugins, + pluginsConfig, + ); + }); + + it('should not start pluginServer for javascript', async () => { + await startScripts._startDevServerWp5([plugin], { ...opts, type: WebpackTypeWp5.JavaScript }, {}); + expect(pluginServer).not.toHaveBeenCalled(); + }); + + it('should start the ipc server and add the delay plugin for static', async () => { + const config = { plugins: [] }; + getConfigurationForWp5.mockResolvedValue(config); + + await startScripts._startDevServerWp5([plugin], { ...opts, type: WebpackTypeWp5.Static }, pluginsConfig); + + expect(startIPCServer).toHaveBeenCalledTimes(1); + expect(startIPCClient).not.toHaveBeenCalled(); + expect(onIPCServerMessage).toHaveBeenCalledTimes(2); + expect(onIPCServerMessage).toHaveBeenCalledWith(ipcServerScriptsWp5.IPCType.onCompileComplete, defaultOnCompile); + expect(onIPCServerMessage).toHaveBeenCalledWith( + ipcServerScriptsWp5.IPCType.onDevServerCrashed, + startScripts._onServerCrashWp5, + ); + expect(config.plugins).toHaveLength(1); + }); + + it('should start the ipc client and use the emitter for javascript', async () => { + await startScripts._startDevServerWp5([plugin], { ...opts, type: WebpackTypeWp5.JavaScript }, {}); + + expect(startIPCClient).toHaveBeenCalledTimes(1); + expect(startIPCServer).not.toHaveBeenCalled(); + expect(compiler).toHaveBeenCalledTimes(1); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + expect(compiler).toHaveBeenCalledWith(expect.any(Object), true, true, emitCompileComplete as any); + }); + + it('should use the default compiler callback and start the dev-server for complete', async () => { + const result = await startScripts._startDevServerWp5( + [plugin], + { ...opts, type: WebpackTypeWp5.Complete }, + pluginsConfig, + ); + + expect(startIPCServer).not.toHaveBeenCalled(); + expect(startIPCClient).not.toHaveBeenCalled(); + expect(compiler).toHaveBeenCalledWith(expect.any(Object), true, false, defaultOnCompile); + expect(webpackDevServer).toHaveBeenCalledTimes(1); + expect(result).toEqual({ port: opts.port }); + }); + + it('should emit dev-server crashed if the compiler throws', async () => { + const err = new Error('compile-failed'); + compiler.mockImplementation(() => { + throw err; + }); + + await startScripts._startDevServerWp5([plugin], { ...opts, type: WebpackTypeWp5.Complete }, pluginsConfig); + + expect(emitDevServerCrashed).toHaveBeenCalledTimes(1); + expect(emitDevServerCrashed).toHaveBeenCalledWith(err); + expect(webpackDevServer).not.toHaveBeenCalled(); + }); + }); + + describe('_onServerCrashWp5', () => { + it('should print message and exit', () => { + jest.spyOn(exit, 'default').mockReturnThis(); + + const payload = { + exception: { + message: 'the-message', + stack: 'the-line', + }, + }; + startScripts._onServerCrashWp5(payload); + + expect(prints.serverCrashed).toHaveBeenCalledTimes(1); + expect(prints.serverCrashed).toHaveBeenCalledWith(payload); + expect(exit.default).toHaveBeenCalledTimes(1); + expect(exit.default).toHaveBeenCalledWith(1); + }); + }); + + describe('_getPluginsConfigurationWp5', () => { + it('should return plugin configuration', () => { + const obj: PluginsConfigWp5 = { + pluginOne: { + port: 100, + }, + pluginTwo: { + port: 200, + }, + }; + const configStr = '{"pluginOne":{"port":100},"pluginTwo":{"port":200}}'; + const args = ['stuff', '--plugin-config', configStr]; + + expect(startScripts._getPluginsConfigurationWp5(...args)).toEqual(obj); + }); + }); + + describe('_requirePackages', () => { + it('should require the plugins and package json files', () => { + const pkgPath = require.resolve('../../../package.json'); + // eslint-disable-next-line @typescript-eslint/no-var-requires, global-require, @typescript-eslint/no-require-imports + const pkg = require(pkgPath); + + const result = startScripts._requirePackages(pkgPath, pkgPath); + + expect(result).toEqual({ plugins: pkg, pkg }); + }); + }); }); diff --git a/packages/flex-plugin-scripts/src/scripts/build.ts b/packages/flex-plugin-scripts/src/scripts/build.ts index 6ebb32582..1c123c3d5 100644 --- a/packages/flex-plugin-scripts/src/scripts/build.ts +++ b/packages/flex-plugin-scripts/src/scripts/build.ts @@ -1,9 +1,10 @@ import { env, logger, exit, Callback } from '@twilio/flex-dev-utils'; import { Environment } from '@twilio/flex-dev-utils/dist/env'; import { addCWDNodeModule, getFileSizeInMB, getPaths, updateAppVersion } from '@twilio/flex-dev-utils/dist/fs'; +import { webpack5, Stats } from '@twilio/flex-plugin-webpack5'; import { webpack, WebpackCompiler } from '@twilio/flex-plugin-webpack'; -import getConfiguration, { ConfigurationType } from '../config'; +import getConfiguration, { ConfigurationType, getConfigurationForWp5 } from '../config'; import { setEnvironment } from '..'; import { buildFailure, buildSuccessful, fileTooLarge } from '../prints'; import run from '../utils/run'; @@ -24,11 +25,47 @@ interface BuildBundle { const MAX_BUILD_SIZE_MB = 10; +/** + * Webpack 5's Stats schema nests related assets (e.g. a chunk's sourcemap) inside that asset's + * own `related` array, rather than listing them as independent top-level entries the way + * Webpack 4 does. Flatten them back into a single list so the printed file count/summary + * includes every emitted file (e.g. the .map), matching Webpack 4's reporting. + * @private + */ +// eslint-disable-next-line import/no-unused-modules +export const _flattenAssetsWp5 = (assets: Bundle[]): Bundle[] => + assets.flatMap((asset) => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const related = ((asset as any).related as Bundle[] | undefined) ?? []; + return [asset, ...related]; + }); + /** * Builds the JS and Sourcemap bundles * @private */ // eslint-disable-next-line import/no-unused-modules +export const _handlerWp5 = + (resolve: Callback, reject: Callback): any => + (err: Error, stats: Stats) => { + if (err) { + logger.info(`error`); + reject(err); + return; + } + + const result = stats.toJson({ all: false, warnings: true, errors: true }); + if (stats.hasErrors()) { + reject(result.errors?.map((e) => e.message) as string[]); + return; + } + + resolve({ + bundles: _flattenAssetsWp5(stats.toJson({ assets: true }).assets as Bundle[]), + warnings: result.warnings?.map((w) => w.message), + }); + }; + export const _handler = (resolve: Callback, reject: Callback): WebpackCompiler.Handler => (err: Error, stats) => { @@ -49,6 +86,20 @@ export const _handler = }); }; +/** + * Promisify the webpack 5 runner + * @private + */ +/* c8 ignore next */ +// eslint-disable-next-line import/no-unused-modules +export const _runWebpack5 = async (): Promise => { + logger.debug('Building Flex plugin bundle in webpack 5'); + return new Promise(async (resolve, reject) => { + const config = await getConfigurationForWp5(ConfigurationType.Webpack, Environment.Production, false); + webpack5(config).run(_handlerWp5(resolve, reject)); + }); +}; + /** * Promisify the webpack runner * @private @@ -66,6 +117,7 @@ export const _runWebpack = async (): Promise => { * Builds the bundle */ const build = async (...argv: string[]): Promise => { + const isWp5 = argv.includes('--wp5'); setEnvironment(...argv); logger.debug('Building Flex plugin bundle'); @@ -84,7 +136,7 @@ const build = async (...argv: string[]): Promise => { logger.newline(); try { - const { warnings, bundles } = await _runWebpack(); + const { warnings, bundles } = isWp5 ? await _runWebpack5() : await _runWebpack(); const bundleSize = getFileSizeInMB(getPaths().app.bundlePath); const sourceMapSize = getFileSizeInMB(getPaths().app.sourceMapPath); diff --git a/packages/flex-plugin-scripts/src/scripts/start.ts b/packages/flex-plugin-scripts/src/scripts/start.ts index 370234db0..c12279ef1 100644 --- a/packages/flex-plugin-scripts/src/scripts/start.ts +++ b/packages/flex-plugin-scripts/src/scripts/start.ts @@ -19,8 +19,24 @@ import { PluginsConfig, DelayRenderStaticPlugin, } from '@twilio/flex-plugin-webpack'; +import { + compilerWp5, + compilerRendererWp5, + emitCompileCompleteWp5, + emitDevServerCrashedWp5, + IPCTypeWp5, + onIPCServerMessageWp5, + pluginServerWp5, + startIPCClientWp5, + startIPCServerWp5, + webpackDevServerWp5, + OnDevServerCrashedPayloadWp5, + PluginsConfigWp5, + DelayRenderStaticPluginWp5, + WebpackTypeWp5, +} from '@twilio/flex-plugin-webpack5'; -import getConfiguration, { ConfigurationType, WebpackType } from '../config'; +import getConfiguration, { ConfigurationType, getConfigurationForWp5, WebpackType } from '../config'; import run from '../utils/run'; import { findFirstLocalPlugin, parseUserInputPlugins, UserInputPlugin } from '../utils/parser'; import { serverCrashed } from '../prints'; @@ -31,6 +47,12 @@ interface StartServerOptions { type: WebpackType; } +interface StartServerOptionsWp5 { + port: number; + remoteAll: boolean; + type: WebpackTypeWp5; +} + export interface StartScript { port: number; } @@ -69,6 +91,15 @@ export const _onServerCrash = (payload: OnDevServerCrashedPayload): void => { exit(1); }; +/** + * Handles server crash wp5 + * @param payload + */ +export const _onServerCrashWp5 = (payload: OnDevServerCrashedPayloadWp5): void => { + serverCrashed(payload); + exit(1); +}; + /** * Parse the configuration * @param args @@ -78,6 +109,14 @@ export const _getPluginsConfiguration = (...args: string[]): PluginsConfig => { return JSON.parse(args[args.indexOf('--plugin-config') + 1]) as PluginsConfig; }; +/** + * Parse the configuration for wp5 + * @param args + * @returns + */ +export const _getPluginsConfigurationWp5 = (...args: string[]): PluginsConfigWp5 => { + return JSON.parse(args[args.indexOf('--plugin-config') + 1]) as PluginsConfigWp5; +}; /** * Starts the webpack dev-server * @param port the port the server is running on @@ -149,6 +188,78 @@ export const _startDevServer = async ( }; }; +/** + * Starts the webpack 5 dev-server + * @param port the port the server is running on + * @param plugins the list of plugins user has requested + * @param type the webpack type + * @param remoteAll whether to request all plugins + * @private + */ +/* c8 ignore next */ +export const _startDevServerWp5 = async ( + plugins: UserInputPlugin[], + options: StartServerOptionsWp5, + pluginsConfig: PluginsConfigWp5, +): Promise => { + logger.debug('Starting local development environment in wp5'); + const { type, port, remoteAll } = options; + const isJavaScriptServer = type === WebpackTypeWp5.JavaScript; + const isStaticServer = type === WebpackTypeWp5.Static; + const config = await getConfigurationForWp5(ConfigurationType.Webpack, Environment.Development, true, type); + const devConfig = await getConfigurationForWp5(ConfigurationType.DevServer, Environment.Development, true, type); + const localPlugins = plugins.filter((p) => !p.remote); + const pluginRequest = { + local: localPlugins.map((p) => p.name), + remote: plugins + .filter((p) => p.remote && !p.version && !localPlugins.some((l) => l.name === p.name)) + .map((p) => p.name), + versioned: plugins + .filter((p) => p.remote && p.version && !localPlugins.some((l) => l.name === p.name)) + .map((p) => `${p.name}@${p.version}`), + }; + const hasRemote = pluginRequest.remote.length > 0 || pluginRequest.versioned.length > 0 || options.remoteAll; + + // compiler render callbacks + const { onCompile, onRemotePlugins } = compilerRendererWp5(port, pluginRequest.local, !isJavaScriptServer, hasRemote); + // Setup plugin's server + if (!isJavaScriptServer) { + const pluginServerConfig = { port, remoteAll }; + pluginServerWp5(pluginRequest, devConfig, pluginServerConfig, onRemotePlugins, pluginsConfig); + } + + // Start IPC Server + if (isStaticServer) { + config?.plugins?.push(new DelayRenderStaticPluginWp5()); + startIPCServerWp5(); + // start-flex will be listening to compilation errors emitted by start-plugin + onIPCServerMessageWp5(IPCTypeWp5.onCompileComplete, onCompile); + onIPCServerMessageWp5(IPCTypeWp5.onDevServerCrashed, _onServerCrashWp5); + } + + // Start IPC Client + if (isJavaScriptServer) { + startIPCClientWp5(); + } + + try { + // Pass either the default onCompile (for start-flex) or the event-emitter (for start-plugin) + const devCompiler = compilerWp5( + config, + true, + isJavaScriptServer, + isJavaScriptServer ? emitCompileCompleteWp5 : onCompile, + ); + webpackDevServerWp5(devCompiler, devConfig, type); + } catch (err) { + await emitDevServerCrashedWp5(err); + } + + return { + port, + }; +}; + /** * Finds the port * @param args @@ -188,9 +299,10 @@ export const start = async (...args: string[]): Promise => { } let type = WebpackType.Complete; + let typeWp5 = WebpackTypeWp5.Complete; if (args[0] === 'flex') { type = WebpackType.Static; - + typeWp5 = WebpackTypeWp5.Static; /* * For some reason start flex sometimes throws this exception * I haven't been able to figure why but it doesn't look like it is crashing the server @@ -205,6 +317,7 @@ export const start = async (...args: string[]): Promise => { }); } else if (args[0] === 'plugin') { type = WebpackType.JavaScript; + typeWp5 = WebpackTypeWp5.JavaScript; env.setWDSSocketPort(port); } @@ -216,12 +329,23 @@ export const start = async (...args: string[]): Promise => { remoteAll: args.includes('--include-remote'), }; + const optionsWp5 = { + port, + typeWp5, + remoteAll: args.includes('--include-remote'), + }; + let pluginsConfig: PluginsConfig = {}; - if (type !== WebpackType.JavaScript) { + let pluginsConfigWp5: PluginsConfigWp5 = {}; + if (type !== WebpackType.JavaScript && args.includes('--wp5')) { + pluginsConfigWp5 = _getPluginsConfigurationWp5(...args); + } else if (type !== WebpackType.JavaScript) { pluginsConfig = _getPluginsConfiguration(...args); } - return _startDevServer(userInputPlugins, options, pluginsConfig); + return args.includes('--wp5') + ? _startDevServerWp5(userInputPlugins, { ...optionsWp5, type: typeWp5 }, pluginsConfigWp5) + : _startDevServer(userInputPlugins, options, pluginsConfig); }; // eslint-disable-next-line @typescript-eslint/no-floating-promises diff --git a/packages/flex-plugin-test/package.json b/packages/flex-plugin-test/package.json index eecdb801e..3c17ed996 100644 --- a/packages/flex-plugin-test/package.json +++ b/packages/flex-plugin-test/package.json @@ -56,7 +56,7 @@ "@jest/types": "^27.0.0" }, "engines": { - "node": "^16 || ^18 || ^20 || ^22" + "node": "^18 || ^20 || ^22 || ^24" }, "publishConfig": { "access": "public" diff --git a/packages/flex-plugin-utils-jest/package.json b/packages/flex-plugin-utils-jest/package.json index f004d780f..a4144df74 100644 --- a/packages/flex-plugin-utils-jest/package.json +++ b/packages/flex-plugin-utils-jest/package.json @@ -36,7 +36,7 @@ "jest-matcher-utils": "^26.6.2" }, "engines": { - "node": "^16 || ^18 || ^20 || ^22" + "node": "^18 || ^20 || ^22 || ^24" }, "publishConfig": { "access": "public" diff --git a/packages/flex-plugin-webpack/package.json b/packages/flex-plugin-webpack/package.json index 3b097cc4a..36c1d818d 100644 --- a/packages/flex-plugin-webpack/package.json +++ b/packages/flex-plugin-webpack/package.json @@ -81,7 +81,7 @@ "typescript": "^4.9.5" }, "engines": { - "node": "^16 || ^18 || ^20 || ^22" + "node": "^18 || ^20 || ^22 || ^24" }, "publishConfig": { "access": "public" diff --git a/packages/flex-plugin-webpack/src/webpack/__tests__/webpack.config.test.ts b/packages/flex-plugin-webpack/src/webpack/__tests__/webpack.config.test.ts index fbb7ebce4..57cf65ac7 100644 --- a/packages/flex-plugin-webpack/src/webpack/__tests__/webpack.config.test.ts +++ b/packages/flex-plugin-webpack/src/webpack/__tests__/webpack.config.test.ts @@ -181,7 +181,6 @@ describe('WebpackConfiguration', () => { describe('_getBasePlugins', () => { const depVersions = { - '@twilio/flex-plugin-scripts': '1.0.0', '@twilio/flex-plugin': '1.1.0', '@twilio/flex-ui': '1.2.0', react: '1.3.0', @@ -196,7 +195,6 @@ describe('WebpackConfiguration', () => { expect.objectContaining({ __FPB_PLUGIN_UNIQUE_NAME: `'${paths.app.name}'`, __FPB_PLUGIN_VERSION: `'${paths.app.version}'`, - __FPB_FLEX_PLUGIN_SCRIPTS_VERSION: `'${depVersions['@twilio/flex-plugin-scripts']}'`, __FPB_FLEX_PLUGIN_VERSION: `'${depVersions['@twilio/flex-plugin']}'`, __FPB_FLEX_UI_VERSION: `'${depVersions['@twilio/flex-ui']}'`, __FPB_REACT_VERSION: `'${depVersions.react}'`, diff --git a/packages/flex-plugin-webpack/src/webpack/webpack.config.ts b/packages/flex-plugin-webpack/src/webpack/webpack.config.ts index 43e7f134e..d15ab7172 100644 --- a/packages/flex-plugin-webpack/src/webpack/webpack.config.ts +++ b/packages/flex-plugin-webpack/src/webpack/webpack.config.ts @@ -236,7 +236,6 @@ export const _getBasePlugins = (environment: Environment): Plugin[] => { const defined = { __FPB_PLUGIN_UNIQUE_NAME: `'${getPaths().app.name}'`, __FPB_PLUGIN_VERSION: `'${getPaths().app.version}'`, - __FPB_FLEX_PLUGIN_SCRIPTS_VERSION: `'${getDependencyVersion('@twilio/flex-plugin-scripts')}'`, __FPB_FLEX_PLUGIN_VERSION: `'${getDependencyVersion('@twilio/flex-plugin')}'`, __FPB_FLEX_UI_VERSION: `'${flexUIVersion}'`, __FPB_REACT_VERSION: `'${reactVersion}'`, @@ -325,6 +324,7 @@ export const _getJSPlugins = (environment: Environment): Plugin[] => { tsconfig: getPaths().app.tsConfigPath, reportFiles: [ '**', + '!**/node_modules/**', '!**/__tests__/**', '!**/__mocks__/**', '!**/?(*.)(spec|test).*', diff --git a/packages/flex-plugin-webpack5/LICENSE b/packages/flex-plugin-webpack5/LICENSE new file mode 100644 index 000000000..b2d5d8b8f --- /dev/null +++ b/packages/flex-plugin-webpack5/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (C) 2018, Twilio, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/packages/flex-plugin-webpack5/README.md b/packages/flex-plugin-webpack5/README.md new file mode 100644 index 000000000..fa89aa1ad --- /dev/null +++ b/packages/flex-plugin-webpack5/README.md @@ -0,0 +1,40 @@ +![npm](https://img.shields.io/npm/v/flex-plugin-webpack5.svg?style=square) +![npm](https://img.shields.io/npm/dt/flex-plugin-webpack5.svg?style=square) +[![NpmLicense](https://img.shields.io/npm/l/flex-plugin-webpack5.svg?style=square)](../../LICENSE) + +# Flex Plugin Webpack 5 + +Webpack 5 configurations for building and running Flex plugins - the Webpack 5 counterpart to +[`@twilio/flex-plugin-webpack`](../flex-plugin-webpack), which remains on Webpack 4 and is still the default. + +This package is not used directly; it is consumed by +[`@twilio/flex-plugin-scripts`](../flex-plugin-scripts), which selects between the two webpack +major versions based on the `--wp5` flag passed to the `flex-plugin build`/`flex-plugin start` +scripts (surfaced through the `twilio flex:plugins:build`/`twilio flex:plugins:start` CLI commands +as `--wp5`). + +Because a project can only ever depend on one version of a given npm package at a time, every +export from this package is named with a `Wp5` suffix (`webpackFactoryWp5`, `compilerWp5`, +`WebpackTypeWp5`, and so on) so it can be imported side by side with `@twilio/flex-plugin-webpack`'s +un-suffixed equivalents without collisions. Its Webpack-version-specific dependencies (`webpack`, +`webpack-dev-server`, `html-webpack-plugin`, `terser-webpack-plugin`, etc.) are similarly installed +under aliased package names (e.g. `webpack5`, `html-webpack-plugin-wp5`) so both webpack majors can +coexist in the same `node_modules` tree without version conflicts. + +## Notable differences from `@twilio/flex-plugin-webpack` + +- Uses `fork-ts-checker-webpack-plugin@^9`, a modern, actively maintained major version compatible + with current TypeScript syntax - unlike webpack 4's still-pinned `^4.1.6`. TypeScript type-checking + prefers the **plugin project's own installed TypeScript** version over this package's own, so a + plugin's dependencies (e.g. newer `@twilio/flex-ui`/`@apollo/client` releases using modern + `.d.ts` syntax) are checked with a compatible compiler rather than failing against a stale one. +- Targets Webpack 5's APIs directly (asset modules, the new `Stats` schema, `processAssets` hooks) + rather than Webpack 4's. + +## Contributors + +Thank you to all the lovely contributors to this project. Please check the main repository to see [all contributors](https://github.com/twilio/flex-plugin-builder#contributors). + +## License + +[MIT](../../LICENSE) diff --git a/packages/flex-plugin-webpack5/jest.config.js b/packages/flex-plugin-webpack5/jest.config.js new file mode 100644 index 000000000..270b54b0d --- /dev/null +++ b/packages/flex-plugin-webpack5/jest.config.js @@ -0,0 +1,15 @@ +const base = require('./../../jest.base.js'); +const pkg = require('./package'); + +module.exports = { + rootDir: '.', + ...base(pkg), + coverageThreshold: { + global: { + statements: 61, + branches: 35, + lines: 58, + functions: 49, + }, + }, +}; diff --git a/packages/flex-plugin-webpack5/package.json b/packages/flex-plugin-webpack5/package.json new file mode 100644 index 000000000..237130b84 --- /dev/null +++ b/packages/flex-plugin-webpack5/package.json @@ -0,0 +1,89 @@ +{ + "name": "@twilio/flex-plugin-webpack5", + "version": "7.1.3", + "description": "Flex Plugin Webpack and Webpack dev-server configurations", + "keywords": [ + "flex", + "plugins", + "scripts", + "twilio", + "webpack" + ], + "homepage": "https://github.com/twilio/flex-plugin-builder", + "bugs": { + "url": "https://github.com/twilio/flex-plugin-builder/issues" + }, + "repository": { + "type": "git", + "url": "git+https://github.com/twilio/flex-plugin-builder.git" + }, + "license": "MIT", + "author": "Flex Runtime ", + "main": "dist/index.js", + "types": "dist/index.d.ts", + "files": [ + "dist" + ], + "scripts": { + "prebuild": "npm run clean", + "build": "cd ../.. && tsc -p \"packages/flex-plugin-webpack5/tsconfig.json\"", + "clean": "rm -rf dist", + "lint": "eslint --ext ts src/", + "lint:fix": "npm run lint -- --fix", + "test": "cd ../.. && jest packages/flex-plugin-webpack5 --color", + "test:watch": "cd ../.. && jest packages/flex-plugin-webpack5 --watch --color" + }, + "dependencies": { + "@babel/core": "^7.22.10", + "@babel/preset-env": "^7.22.10", + "@babel/preset-modules": "^0.1.6", + "@babel/preset-react": "^7.22.5", + "@babel/preset-typescript": "^7.22.11", + "@k88/cra-webpack-hot-dev-client": "^1.1.0", + "@k88/format-webpack-messages": "^1.1.0", + "@k88/interpolate-html-plugin": "^1.0.5", + "@k88/module-scope-plugin": "^1.1.0", + "@twilio/flex-dev-utils": "^7.1.0", + "@types/express-serve-static-core": "^4.17.35", + "babel-loader": "^9.1.3", + "babel-plugin-named-asset-import": "^0.3.8", + "babel-preset-react-app": "^10.0.1", + "css-loader-wp5": "npm:css-loader@^6.8.1", + "dotenv": "^10.0.0", + "dotenv-webpack-wp5": "npm:dotenv-webpack@^8.0.1", + "fork-ts-checker-webpack-plugin": "^9.1.0", + "html-webpack-plugin-wp5": "npm:html-webpack-plugin@^5.5.3", + "lodash": "^4.17.21", + "node-ipc": "9.1.4", + "pnp-webpack-plugin": "^1.7.0", + "postcss": "^8.2.8", + "postcss-flexbugs-fixes": "^5.0.2", + "postcss-loader-wp5": "npm:postcss-loader@^7.3.3", + "postcss-preset-env": "^6.7.0", + "resolve-url-loader": "^4.0.0", + "sass": "^1.32.8", + "sass-loader-wp5": "npm:sass-loader@^13.3.2", + "style-loader-wp5": "npm:style-loader@^3.3.3", + "tapable": "^1.1.3", + "terser-webpack-plugin-wp5": "npm:terser-webpack-plugin@^2.3.8", + "ts-pnp": "^1.2.0", + "url-loader": "^4.1.1", + "webpack": "5.88.2", + "webpack-dev-server-wp5": "npm:webpack-dev-server@^4.15.1", + "webpack5": "npm:webpack@5.88.2" + }, + "devDependencies": { + "@types/dotenv-webpack": "npm:@types/dotenv-webpack@^6.0.0", + "@types/node-ipc": "9.1.3", + "@types/tapable": "^1.0.8", + "@types/terser-webpack-plugin-wp5": "npm:@types/terser-webpack-plugin@^2.2.1", + "express-serve-static-core": "^0.1.1", + "typescript": "^4.9.5" + }, + "engines": { + "node": "^18 || ^20 || ^22 || ^24" + }, + "publishConfig": { + "access": "public" + } +} diff --git a/packages/flex-plugin-webpack5/src/compiler.ts b/packages/flex-plugin-webpack5/src/compiler.ts new file mode 100644 index 000000000..0f0039a71 --- /dev/null +++ b/packages/flex-plugin-webpack5/src/compiler.ts @@ -0,0 +1,228 @@ +/* c8 ignore start */ + +import { logger, FunctionalCallback } from '@twilio/flex-dev-utils'; +import { FlexPluginError } from '@twilio/flex-dev-utils/dist/errors'; +import { AsyncSeriesHook, SyncHook } from 'tapable'; +import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; +import type { Issue } from 'fork-ts-checker-webpack-plugin/lib/issue/issue'; +import webpack, { Compiler as WebpackCompiler, Configuration, StatsError, WebpackError, Stats } from 'webpack5'; +import { getCliPaths, getPaths, readRunPluginsJson, writeJSONFile } from '@twilio/flex-dev-utils/dist/fs'; +import webpackFormatMessages from '@k88/format-webpack-messages'; +import { getLocalAndNetworkUrls } from '@twilio/flex-dev-utils/dist/urls'; + +import { OnCompileCompletePayload } from './devServer/ipcServer'; +import { OnRemotePlugins, Plugin } from './devServer/pluginServer'; +import { devServerSuccessful } from './prints'; +import ToJsonOutput = webpack.StatsCompilation; + +interface ErrorsAndWarnings { + errors: StatsError[] | WebpackError[] | string[]; + warnings: StatsError[] | WebpackError[] | string[]; +} + +type OnCompile = (payload: OnCompileCompletePayload) => void; +interface OnCompileResult { + [key: string]: ToJsonOutput; +} +interface CompilerHooks { + beforeCompile: AsyncSeriesHook<[any]>; + done: AsyncSeriesHook; + invalid: SyncHook<[null | string, number]>; +} +interface Hook extends CompilerHooks { + tsCompiled: SyncHook; +} +// @ts-ignore +export interface Compiler extends WebpackCompiler { + hooks: Hook; +} +interface CompilerRenderer { + onCompile: OnCompile; + onRemotePlugins: OnRemotePlugins; +} + +// Holds all compilation errors +const results: OnCompileResult = {}; + +/** + * Creates a webpack compiler + * + * @param config the Webpack configuration + * @param devServer whether to run the devserver or not + * @param type the webpack compile type + * @param localPlugins the names of plugins to run locally + */ +/* c8 ignore next */ +export default ( + config: Configuration, + devServer: boolean, + isJavaScriptServer: boolean, + onCompile: OnCompile, +): Compiler => { + logger.debug('Creating webpack compiler'); + + try { + const compiler: Compiler = webpack(config) as unknown as Compiler; + if (!Object.isExtensible(compiler.hooks)) { + compiler.hooks = { ...compiler.hooks }; + } + compiler.hooks.tsCompiled = new SyncHook(['warnings', 'errors']); + + // For build, we don't need to tap into any hooks + if (!devServer) { + return compiler; + } + let tsMessagesPromise: Promise; + let tsMessagesResolver: FunctionalCallback; + + if (getPaths().app.isTSProject()) { + compiler.hooks.beforeCompile.tap('beforeCompile', () => { + tsMessagesPromise = new Promise((resolve) => { + tsMessagesResolver = (msgs: ErrorsAndWarnings) => resolve(msgs); + }); + }); + + /* + * fork-ts-checker-webpack-plugin resolves its own nested copy of the `webpack` peer dependency, + * which TypeScript sees as a distinct (though compatible) Compiler type from our own webpack5 import. + */ + ForkTsCheckerWebpackPlugin.getCompilerHooks( + compiler as unknown as Parameters[0], + ).issues.tap('afterTSCheck', (issues: Issue[]) => { + const format = (issue: Issue) => { + const location = issue.location ? `:${issue.location.start.line}:${issue.location.start.column}` : ''; + + return `${issue.file ?? ''}${location}\n${issue.code}: ${issue.message}`; + }; + + if (tsMessagesResolver) { + tsMessagesResolver({ + errors: issues.filter((issue) => issue.severity === 'error').map(format), + warnings: issues.filter((issue) => issue.severity === 'warning').map(format), + }); + } + + // issues is a SyncWaterfallHook - must return the (possibly filtered) issues to pass along + return issues; + }); + } + + // invalid is `bundle invalidated` and is invoked when files are modified in dev-server. + compiler.hooks.invalid.tap('invalid', () => { + logger.clearTerminal(); + logger.info(`Re-compiling **${getPaths().app.name}**`); + }); + + compiler.hooks.done.tap('done', async (stats) => { + const result = stats?.toJson({ all: false, errors: true, warnings: true }); + if (getPaths().app.isTSProject() && !stats.hasErrors()) { + const delayedMsg = setTimeout(() => { + logger.notice('Waiting for Typescript check results...'); + }, 100); + const messages = await tsMessagesPromise; + clearTimeout(delayedMsg); + + // Push ts-compile errors into compiler + result?.errors?.push(...(messages.errors as StatsError[])); + stats.compilation.errors.push(...(messages.errors as WebpackError[])); + result?.warnings?.push(...(messages.warnings as StatsError[])); + stats.compilation.warnings.push(...(messages.warnings as WebpackError[])); + + compiler.hooks.tsCompiled.call(messages.warnings as string[], messages.errors as string[]); + } + + const config = readRunPluginsJson(); + + // Add the plugin to the loaded plugins configuration file + if (isJavaScriptServer) { + config.loadedPlugins.push(getPaths().app.name); + writeJSONFile(config, getCliPaths().localPluginsJsonPath); + } + + // Check to see if the plugin is the last bundle to be loaded + onCompile({ + result, + appName: getPaths().app.name, + lastPluginBundle: config.plugins.length === config.loadedPlugins.length, + }); + }); + + return compiler; + } catch (err) { + // @ts-ignore + throw new FlexPluginError(`Failed to create a webpack compiler: ${err.message}`); + } +}; + +/** + * Prints the errors and warnings or a successful message when compilation finishes + * @param port the port the server is running on + * @param localPlugins the local plugins running + * @param showSuccessMsg whether to show succecss message or not + * @param hasRemote whether there are any remote plugins + */ +export const compilerRenderer = ( + port: number, + localPlugins: string[], + showSuccessMsg: boolean, + hasRemote: boolean, +): CompilerRenderer => { + const { local, network } = getLocalAndNetworkUrls(port); + const remotePlugins: Plugin[] = []; + const serverSuccessful = (list: Plugin[]) => { + list.forEach((l) => { + if (!remotePlugins.some((r) => r.name === l.name)) { + remotePlugins.push(l); + } + }); + + logger.clearTerminal(); + devServerSuccessful(local, network, localPlugins, remotePlugins, hasRemote); + }; + + return { + onRemotePlugins: serverSuccessful, + onCompile: ({ result, appName }) => { + logger.clearTerminal(); + results[appName] = result; + + const isSuccessful = Object.values(results).every( + (r) => r.errors && r.errors.length === 0 && r.warnings && r.warnings.length === 0, + ); + if (isSuccessful) { + if (showSuccessMsg) { + serverSuccessful([]); + } + return; + } + + Object.keys(results).forEach((name) => { + const formatted = webpackFormatMessages({ + errors: results[name].errors as unknown as string[], + warnings: results[name].warnings as unknown as string[], + }); + + // Only show errors if both exist + if ((results[name].errors as unknown as string[]).length) { + /* + * Most errors are duplicate of the same error + * So only show the first error + */ + formatted.errors.length = 1; + + logger.error(`Failed to compile plugin ${logger.colors.red.bold(name)}.`); + logger.info(formatted.errors.join('\n')); + logger.newline(); + return; + } + + if ((results[name].warnings as unknown as string[]).length) { + logger.warning(`Compiled plugin ${logger.colors.yellow.bold(name)} with warning(s).`); + logger.info(formatted.warnings.join('\n')); + logger.newline(); + } + }); + }, + }; +}; +/* c8 ignore stop */ diff --git a/packages/flex-plugin-webpack5/src/devServer/__tests__/ipcServer.test.ts b/packages/flex-plugin-webpack5/src/devServer/__tests__/ipcServer.test.ts new file mode 100644 index 000000000..ffb51804f --- /dev/null +++ b/packages/flex-plugin-webpack5/src/devServer/__tests__/ipcServer.test.ts @@ -0,0 +1,71 @@ +import * as ipcServerScripts from '../ipcServer'; + +describe('ipcServer', () => { + beforeEach(() => { + jest.resetAllMocks(); + }); + + it('should append to queue and process queue on emit', async () => { + const _processEmitQueue = jest.spyOn(ipcServerScripts, '_processEmitQueue').mockReturnThis(); + + // @ts-ignore + await ipcServerScripts._emitToServer(null, null); + + expect(_processEmitQueue).toHaveBeenCalledTimes(1); + }); + + it('should test emitCompileComplete for a plugin that is not the last to load', async () => { + const _emitAllCompilesComplete = jest.spyOn(ipcServerScripts, 'emitAllCompilesComplete').mockReturnThis(); + const _emitToServer = jest.spyOn(ipcServerScripts, '_emitToServer').mockReturnThis(); + + const payload = { + result: {} as any, + appName: 'test', + lastPluginBundle: false, + }; + await ipcServerScripts.emitCompileComplete(payload); + + expect(_emitToServer).toHaveBeenCalledTimes(1); + expect(_emitToServer).toHaveBeenCalledWith(ipcServerScripts.IPCType.onCompileComplete, payload); + expect(_emitAllCompilesComplete).not.toHaveBeenCalled(); + }); + + it('should test emitCompileComplete for a plugin that is the last to load', async () => { + const _emitAllCompilesComplete = jest.spyOn(ipcServerScripts, 'emitAllCompilesComplete').mockReturnThis(); + const _emitToServer = jest.spyOn(ipcServerScripts, '_emitToServer').mockReturnThis(); + + const payload = { + result: {} as any, + appName: 'test', + lastPluginBundle: true, + }; + await ipcServerScripts.emitCompileComplete(payload); + + expect(_emitToServer).toHaveBeenCalledTimes(1); + expect(_emitToServer).toHaveBeenCalledWith(ipcServerScripts.IPCType.onCompileComplete, payload); + expect(_emitAllCompilesComplete).toHaveBeenCalledTimes(1); + }); + + it('should test emitDevServerCrashed', async () => { + const _emitToServer = jest.spyOn(ipcServerScripts, '_emitToServer').mockReturnThis(); + + const err = new Error('some-error'); + const payload = { + exception: { + message: 'some-error', + stack: expect.any(String), + }, + }; + await ipcServerScripts.emitDevServerCrashed(err); + + expect(_emitToServer).toHaveBeenCalledTimes(1); + expect(_emitToServer).toHaveBeenCalledWith(ipcServerScripts.IPCType.onDevServerCrashed, payload); + }); + + it('should process queue on client connect', async () => { + const _processEmitQueue = jest.spyOn(ipcServerScripts, '_processEmitQueue').mockReturnThis(); + + await ipcServerScripts._onClientConnected(); + expect(_processEmitQueue).toHaveBeenCalledTimes(1); + }); +}); diff --git a/packages/flex-plugin-webpack5/src/devServer/__tests__/pluginServer.test.ts b/packages/flex-plugin-webpack5/src/devServer/__tests__/pluginServer.test.ts new file mode 100644 index 000000000..0f733bca5 --- /dev/null +++ b/packages/flex-plugin-webpack5/src/devServer/__tests__/pluginServer.test.ts @@ -0,0 +1,308 @@ +import * as fsScript from '@twilio/flex-dev-utils/dist/fs'; +import { Request, Response } from 'express-serve-static-core'; +import { FlexPluginError } from '@twilio/flex-dev-utils'; + +import * as pluginServerScript from '../pluginServer'; + +jest.mock('@twilio/flex-dev-utils/dist/logger/lib/logger'); + +describe('pluginServer', () => { + const pluginName = 'plugin-test'; + const pluginDir = 'the-dir'; + const defaultPluginName = 'default-plugin'; + + const paths = { + app: { + name: defaultPluginName, + }, + }; + + const pkg: fsScript.PackageJson = { + name: defaultPluginName, + version: '1.2.3', + dependencies: {}, + devDependencies: {}, + }; + + beforeEach(() => { + jest.clearAllMocks(); + + // @ts-ignore + jest.spyOn(fsScript, 'getPaths').mockReturnValue(paths); + }); + + describe('_getLocalPlugin', () => { + const plugin = { name: pluginName, dir: pluginDir }; + jest.spyOn(fsScript, 'readPluginsJson').mockReturnValue({ plugins: [plugin] }); + + it('should find the plugin', () => { + expect(pluginServerScript._getLocalPlugin(pluginName)).toEqual(plugin); + }); + + it('should not find the plugin', () => { + expect(pluginServerScript._getLocalPlugin('unknown')).toBeUndefined(); + }); + }); + + describe(' _getLocalPlugins', () => { + const readPluginsJson = jest + .spyOn(fsScript, 'readPluginsJson') + .mockReturnValue({ plugins: [{ name: pluginName, dir: pluginDir }] }); + + it('should return the plugin if found', () => { + const result = pluginServerScript._getLocalPlugins(3000, [pluginName]); + expect(result).toEqual([ + { + phase: 3, + name: pluginName, + src: `http://localhost:3000/plugins/${pluginName}.js`, + }, + ]); + }); + + it('should throw error', (done) => { + try { + pluginServerScript._getLocalPlugins(3000, ['plugin-unknown']); + } catch (e) { + expect(e).toBeInstanceOf(FlexPluginError); + expect(readPluginsJson).toHaveBeenCalledTimes(1); + expect(e.message).toContain('was not locally found'); + done(); + } + }); + }); + + describe('_getRemoteVersionedPlugins', () => { + const plugin = 'plugin-version@1.0.0'; + const badPlugin = '!'; + + it('should return the versioned plugin', () => { + const result = pluginServerScript._getRemoteVersionedPlugins([plugin]); + expect(result).toEqual([ + { + phase: 3, + name: 'plugin-version', + src: 'https://flex.twilio.com/plugins/v1/plugin-version/1.0.0/bundle.js', + version: '1.0.0', + }, + ]); + }); + + it('should throw error', (done) => { + try { + pluginServerScript._getRemoteVersionedPlugins([badPlugin]); + } catch (e) { + expect(e).toBeInstanceOf(FlexPluginError); + expect(e.message).toContain('Unexpected plugin name format was provided'); + done(); + } + }); + }); + + describe('_mergePlugins', () => { + it('should return both remote and local plugins', () => { + const localPlugin = { + name: defaultPluginName, + phase: 3, + } as pluginServerScript.Plugin; + const remotePluginOne = { + name: 'plugin-remote-1', + phase: 3, + } as pluginServerScript.Plugin; + const remotePluginTwo = { + name: 'plugin-remote-2', + phase: 3, + } as pluginServerScript.Plugin; + + jest.spyOn(pluginServerScript, '_getLocalPlugins').mockReturnValue([localPlugin]); + jest.spyOn(fsScript, 'readPackageJson').mockReturnValue(pkg); + jest.spyOn(fsScript, 'readPluginsJson').mockReturnValue({ plugins: [{ name: 'test-name', dir: pluginDir }] }); + + const plugins = pluginServerScript._mergePlugins([localPlugin], [remotePluginOne, remotePluginTwo], []); + + expect(plugins).toHaveLength(3); + }); + + it('should return remote plugins that are not being run locally', () => { + const localPlugin = { + name: 'plugin-1', + phase: 3, + } as pluginServerScript.Plugin; + const remotePluginOne = { + name: 'plugin-1', + phase: 3, + } as pluginServerScript.Plugin; + const remotePluginTwo = { + name: 'plugin-2', + phase: 3, + } as pluginServerScript.Plugin; + + jest.spyOn(pluginServerScript, '_getLocalPlugins').mockReturnValue([localPlugin]); + jest.spyOn(fsScript, 'readPackageJson').mockReturnValue(pkg); + jest.spyOn(fsScript, 'readPluginsJson').mockReturnValue({ plugins: [{ name: 'test-name', dir: pluginDir }] }); + + const plugins = pluginServerScript._mergePlugins([localPlugin], [remotePluginOne, remotePluginTwo], []); + + expect(plugins).toHaveLength(2); + }); + + it('should return remote, version, and local plugins', () => { + const localPlugin = { + name: defaultPluginName, + phase: 3, + } as pluginServerScript.Plugin; + const remotePlugin = { + name: 'plugin-remote', + phase: 3, + } as pluginServerScript.Plugin; + const versionPlugin = { + name: 'plugin-version', + phase: 3, + version: '1.0.0', + } as pluginServerScript.Plugin; + + jest.spyOn(pluginServerScript, '_getLocalPlugins').mockReturnValue([localPlugin]); + jest.spyOn(fsScript, 'readPackageJson').mockReturnValue(pkg); + jest.spyOn(fsScript, 'readPluginsJson').mockReturnValue({ plugins: [{ name: 'test-name', dir: pluginDir }] }); + + const plugins = pluginServerScript._mergePlugins([localPlugin], [remotePlugin], [versionPlugin]); + + expect(plugins).toHaveLength(3); + }); + + it('should return remote plugins that are not local', () => { + const localPlugin = { + name: defaultPluginName, + phase: 3, + } as pluginServerScript.Plugin; + const remotePlugin = { + name: 'plugin-remote', + phase: 3, + } as pluginServerScript.Plugin; + const remotePlugin2 = { + name: defaultPluginName, + phase: 3, + } as pluginServerScript.Plugin; + const versionPlugin = { + name: 'plugin-version', + phase: 3, + version: '1.0.0', + } as pluginServerScript.Plugin; + + jest.spyOn(pluginServerScript, '_getLocalPlugins').mockReturnValue([localPlugin]); + jest.spyOn(pluginServerScript, '_getRemotePlugins').mockResolvedValue([remotePlugin, remotePlugin2]); + jest.spyOn(pluginServerScript, '_getRemoteVersionedPlugins').mockReturnValue([versionPlugin]); + jest.spyOn(fsScript, 'readPackageJson').mockReturnValue(pkg); + jest.spyOn(fsScript, 'readPluginsJson').mockReturnValue({ plugins: [{ name: 'test-name', dir: pluginDir }] }); + + const plugins = pluginServerScript._mergePlugins([localPlugin], [remotePlugin, remotePlugin2], [versionPlugin]); + + expect(plugins).toHaveLength(3); + expect(plugins).toEqual([localPlugin, remotePlugin, versionPlugin]); + }); + }); + + describe('_startServer', () => { + const port = 9000; + const plugins = { + local: ['plugin-local1', 'plugin-local2'], + remote: ['plugin-remote1', 'plugin-remote2'], + versioned: ['plugin-remote2'], + }; + const config = { port, remoteAll: true }; + const jweHeaders = { 'x-flex-jwe': 'jweToken' }; + const getReqResp = (method: string, headers: Record) => { + // @ts-ignore + const resp = { + writeHead: jest.fn(), + end: jest.fn(), + } as Response; + const req = { method, headers } as Request; + + return { req, resp }; + }; + const onRemotePlugins = jest.fn(); + + it('should return 200 for OPTIONS request', async () => { + const { req, resp } = getReqResp('OPTIONS', {}); + const _getHeaders = jest.spyOn(pluginServerScript, '_getHeaders').mockReturnValue({ header: 'true' }); + + await pluginServerScript._startServer(plugins, config, onRemotePlugins)(req, resp); + + expect(_getHeaders).toHaveBeenCalledTimes(1); + expect(resp.writeHead).toHaveBeenCalledTimes(1); + expect(resp.writeHead).toHaveBeenCalledWith(200, { header: 'true' }); + expect(resp.end).toHaveBeenCalledTimes(1); + }); + + it('should 404 for non GET requests', async () => { + const { req, resp } = getReqResp('POST', {}); + jest.spyOn(pluginServerScript, '_getHeaders').mockReturnValue({ header: 'true' }); + + await pluginServerScript._startServer(plugins, config, onRemotePlugins)(req, resp); + + expect(resp.writeHead).toHaveBeenCalledTimes(1); + expect(resp.writeHead).toHaveBeenCalledWith(404, { header: 'true' }); + expect(resp.end).toHaveBeenCalledTimes(1); + }); + + it('should 400 if no jwe token is provided', async () => { + const { req, resp } = getReqResp('GET', {}); + jest.spyOn(pluginServerScript, '_getHeaders').mockReturnValue({ header: 'true' }); + + await pluginServerScript._startServer(plugins, config, onRemotePlugins)(req, resp); + + expect(resp.writeHead).toHaveBeenCalledTimes(1); + expect(resp.writeHead).toHaveBeenCalledWith(400, { header: 'true' }); + expect(resp.end).toHaveBeenCalledTimes(1); + }); + + it('should getPlugins and rebase', async () => { + const { req, resp } = getReqResp('GET', jweHeaders); + const remotePlugin = [{ name: 'plugin-2' }] as pluginServerScript.Plugin[]; + + jest.spyOn(pluginServerScript, '_getHeaders').mockReturnValue({ header: 'true' }); + const _getRemotePlugins = jest.spyOn(pluginServerScript, '_getRemotePlugins').mockResolvedValue(remotePlugin); + const _getRemoteVersionedPlugins = jest + .spyOn(pluginServerScript, '_getRemoteVersionedPlugins') + .mockReturnValue([]); + const _mergePlugins = jest + .spyOn(pluginServerScript, '_mergePlugins') + .mockReturnValue([{ name: 'plugin-1' }, { name: 'plugin-2' }] as pluginServerScript.Plugin[]); + jest.spyOn(fsScript, 'readPluginsJson').mockReturnValue({ plugins: [{ name: 'plugin-1', dir: pluginDir }] }); + + await pluginServerScript._startServer(plugins, config, onRemotePlugins)(req, resp); + + expect(resp.writeHead).toHaveBeenCalledTimes(1); + expect(resp.writeHead).toHaveBeenCalledWith(200, { header: 'true' }); + expect(_getRemotePlugins).toHaveBeenCalledTimes(1); + expect(_getRemotePlugins).toHaveBeenCalledWith('jweToken', undefined); + expect(_getRemoteVersionedPlugins).toHaveBeenCalledTimes(1); + expect(_getRemoteVersionedPlugins).toHaveBeenCalledWith(plugins.versioned); + expect(_mergePlugins).toHaveBeenCalledTimes(1); + expect(onRemotePlugins).toHaveBeenCalledTimes(1); + expect(onRemotePlugins).toHaveBeenCalledWith(remotePlugin); + expect(resp.end).toHaveBeenCalledTimes(1); + expect(resp.end).toHaveBeenCalledWith('[{"name":"plugin-1"},{"name":"plugin-2"}]'); + }); + + it('should fail', async () => { + const { req, resp } = getReqResp('GET', jweHeaders); + + jest.spyOn(pluginServerScript, '_getHeaders').mockReturnValue({ header: 'true' }); + const _getRemotePlugins = jest.spyOn(pluginServerScript, '_getRemotePlugins').mockRejectedValue('failed-message'); + const _mergePlugins = jest.spyOn(pluginServerScript, '_mergePlugins'); + jest.spyOn(fsScript, 'readPluginsJson').mockReturnValue({ plugins: [{ name: 'test-name', dir: pluginDir }] }); + + await pluginServerScript._startServer(plugins, config, onRemotePlugins)(req, resp); + + expect(resp.writeHead).toHaveBeenCalledTimes(1); + expect(resp.writeHead).toHaveBeenCalledWith(500, { header: 'true' }); + expect(_getRemotePlugins).toHaveBeenCalledTimes(1); + expect(_getRemotePlugins).toHaveBeenCalledWith('jweToken', undefined); + expect(_mergePlugins).not.toHaveBeenCalled(); + expect(resp.end).toHaveBeenCalledTimes(1); + expect(resp.end).toHaveBeenCalledWith('failed-message'); + }); + }); +}); diff --git a/packages/flex-plugin-webpack5/src/devServer/ipcServer.ts b/packages/flex-plugin-webpack5/src/devServer/ipcServer.ts new file mode 100644 index 000000000..23ad6a21e --- /dev/null +++ b/packages/flex-plugin-webpack5/src/devServer/ipcServer.ts @@ -0,0 +1,194 @@ +import ipc from 'node-ipc'; +import { env, logger } from '@twilio/flex-dev-utils'; +import webpack from 'webpack5'; + +/* + * Self-import so internal calls between these exports go through the (spy-able) module namespace + * rather than a fixed local binding - lets jest.spyOn intercept same-module calls in tests. + */ +// eslint-disable-next-line import/no-self-import +import * as self from './ipcServer'; +import ToJsonOutput = webpack.StatsCompilation; + +interface Client { + on(event: string, callback: (...args: unknown[]) => void): Client; + emit(event: string, value?: unknown): Client; +} + +export enum IPCType { + onCompileComplete = 'onCompileComplete', + onDevServerCrashed = 'onDevServerCrashed', + onEmitAllCompilesComplete = 'onEmitAllCompilesComplete', +} + +export interface OnCompileCompletePayload { + result: ToJsonOutput; + appName: string; + lastPluginBundle: boolean; +} + +export interface OnDevServerCrashedPayload { + exception: { + message: string; + stack?: string; + }; +} + +interface IPCPayload { + onCompileComplete: OnCompileCompletePayload; + onDevServerCrashed: OnDevServerCrashedPayload; + onEmitAllCompilesComplete: unknown; +} + +type MessageCallback = (payload: IPCPayload[T]) => void; +type MessageCallbacks = { [key in IPCType]?: MessageCallback[] }; + +ipc.config.id = 'twilio.flex.plugin-builder'; +ipc.config.retry = 1500; +ipc.config.silent = !env.isDebug(); + +let _isServerRunning: boolean = false; +let _isClientConnected: boolean = false; +/* c8 ignore next */ +const isServerRunning = (): boolean => _isServerRunning; +/* c8 ignore next */ +const isClientConnected = (): boolean => _isClientConnected; + +let clientNode: Client | null = null; +const messageCallbacks: MessageCallbacks = {}; + +/* + * This is used only to set the type of this queue + * This is the only way to get dynamic typing in TS :( + */ +const getEmitItem = (type?: T, payload?: IPCPayload[T]) => ({ type, payload }); +const emitQueue = [getEmitItem()].slice(1); + +/** + * Processes the emit queue + * @private + */ +/* c8 ignore next */ +export const _processEmitQueue = async (): Promise => { + if (!isClientConnected()) { + return; + } + + while (emitQueue.length) { + (clientNode as Client).emit('message', emitQueue.pop()); + } +}; + +/** + * Processes the on server message + * @param data + * @private + */ +const _onServerMessage = (data: { payload: unknown; type: string }): void => { + if (!data.type) { + logger.error('IPC got an unexpected message: ', data); + return; + } + + Object.keys(messageCallbacks) + .filter((type) => type === data.type) + .forEach((type) => { + if (messageCallbacks[type as IPCType]) { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + messageCallbacks[type as IPCType]?.forEach((cb: MessageCallback) => cb(data.payload)); + } + }); +}; + +/** + * Processes on client connected + * @private + */ +export const _onClientConnected = async (): Promise => { + _isClientConnected = true; + await self._processEmitQueue(); +}; + +/** + * Emits to the server + * @param type the event type + * @param payload the event payload + * @private + */ +export const _emitToServer = async (type: T, payload: IPCPayload[T]): Promise => { + emitQueue.push({ type, payload }); + await self._processEmitQueue(); +}; + +/** + * Starts an IPC server + */ +export const startIPCServer = (): void => { + if (isServerRunning()) { + return; + } + + ipc.serve(() => ipc.server.on('message', _onServerMessage)); + ipc.server.start(); + + _isServerRunning = true; +}; + +/** + * Starts an IPC Client + */ +export const startIPCClient = (): void => { + if (isClientConnected()) { + return; + } + + ipc.connectTo(ipc.config.id, () => { + clientNode = ipc.of[ipc.config.id] as Client; + clientNode.on('connect', _onClientConnected); + }); +}; + +/** + * onMessage event for the IPC server + * @param type + * @param callback + */ +/* c8 ignore next */ +export const onIPCServerMessage = (type: T, callback: MessageCallback): void => { + if (!(type in messageCallbacks)) { + messageCallbacks[type as IPCType] = []; + } + // @ts-ignore + messageCallbacks[type].push(callback); +}; + +/** + * Emits to the server that all of the JS Bundles have completed compiling + * @param payload + * @returns + */ +export const emitAllCompilesComplete = async (): Promise => + self._emitToServer(IPCType.onEmitAllCompilesComplete, {}); + +/** + * Emits a compilation complete event + * @param payload + */ +export const emitCompileComplete = async (payload: OnCompileCompletePayload): Promise => { + await self._emitToServer(IPCType.onCompileComplete, payload); + if (payload.lastPluginBundle) { + await self.emitAllCompilesComplete(); + } +}; + +/** + * Emits a dev-server failed event + * @param error + */ +export const emitDevServerCrashed = async (error: Error): Promise => + self._emitToServer(IPCType.onDevServerCrashed, { + exception: { + message: error.message, + stack: error.stack, + }, + }); diff --git a/packages/flex-plugin-webpack5/src/devServer/pluginServer.ts b/packages/flex-plugin-webpack5/src/devServer/pluginServer.ts new file mode 100644 index 000000000..9bc6bf81f --- /dev/null +++ b/packages/flex-plugin-webpack5/src/devServer/pluginServer.ts @@ -0,0 +1,290 @@ +import https from 'https'; + +import { logger, FlexPluginError, exit, env } from '@twilio/flex-dev-utils'; +import { Request, Response } from 'express-serve-static-core'; +import { FlexConfigurationPlugin, readPluginsJson } from '@twilio/flex-dev-utils/dist/fs'; +import { Configuration, Port } from 'webpack-dev-server-wp5'; + +import { remotePluginNotFound } from '../prints'; +/* + * Self-import so internal calls between these exports go through the (spy-able) module + * namespace rather than a fixed local binding - lets jest.spyOn intercept same-module calls in tests. + */ +// eslint-disable-next-line import/no-self-import +import * as self from './pluginServer'; + +export const PLUGIN_INPUT_PARSER_REGEX = /([\w-]+)(?:@(\S+))?/; + +export interface Plugin { + phase: number; + name: string; + src: string; + version?: string; +} + +interface StartServerPlugins { + local: string[]; + remote: string[]; + versioned: string[]; +} + +interface StartServerConfig { + port: Port | number; + remoteAll: boolean; +} + +export interface PluginsConfig { + [pluginName: string]: { + port: number; + }; +} + +export type OnRemotePlugins = (remotePlugins: Plugin[]) => void; + +/** + * Returns the plugin from the local configuration file + * @param name the plugin name + * @private + */ +// eslint-disable-next-line import/no-unused-modules +export const _getLocalPlugin = (name: string): FlexConfigurationPlugin | undefined => { + return readPluginsJson().plugins.find((p: FlexConfigurationPlugin) => p.name === name); +}; + +/** + * Returns local plugins from cli/plugins.json + * @private + */ +// eslint-disable-next-line import/no-unused-modules +export const _getLocalPlugins = (port: number, names: string[]): Plugin[] => { + const protocol = `http${env.isHTTPS() ? 's' : ''}://`; + + return names.map((name) => { + const match = self._getLocalPlugin(name); + + if (match) { + return { + phase: 3, + name, + src: `${protocol}localhost:${port}/plugins/${name}.js`, + }; + } + + throw new FlexPluginError( + `The plugin ${name} was not locally found. Try running \`npm install\` once in the plugin directory and try again.`, + ); + }); +}; + +/** + * Generates the response headers + * + * @private + */ +// eslint-disable-next-line import/no-unused-modules +export const _getHeaders = (): Record => ({ + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET', + 'Access-Control-Allow-Headers': 'Content-Type, X-Flex-Version, X-Flex-JWE', + 'Access-Control-Allow-Credentials': 'true', + 'Content-Type': 'application/json', +}); + +/** + * Fetches the Plugins from Flex + * + * @param token the JWE Token + * @param version the Flex version + */ +/* c8 ignore next */ +// eslint-disable-next-line import/no-unused-modules +export const _getRemotePlugins = async (token: string, version: string | null | undefined): Promise => { + return new Promise((resolve, reject) => { + const headers = { + 'X-Flex-JWE': token, + }; + if (version) { + headers['X-Flex-Version'] = version; + } + + const options = { + hostname: 'flex.twilio.com', + port: 443, + path: '/plugins', + method: 'GET', + headers, + }; + + https + .request(options, (res) => { + const data: Buffer[] = []; + + res.on('data', (chunk) => data.push(chunk)); + res.on('end', () => resolve(JSON.parse(Buffer.concat(data).toString()).filter((p: Plugin) => p.phase >= 3))); + }) + .on('error', reject) + .end(); + }); +}; + +/** + * Returns versioned plugins from the CLI + * + * @param names + * @returns + */ +export const _getRemoteVersionedPlugins = (names: string[]): Plugin[] => { + return names.map((plugin) => { + const groups = plugin.match(PLUGIN_INPUT_PARSER_REGEX); + + if (!groups) { + throw new FlexPluginError('Unexpected plugin name format was provided'); + } + + const name = groups[1]; + const version = groups[2]; + + return { + phase: 3, + name, + src: `https://flex.twilio.com/plugins/v1/${name}/${version}/bundle.js`, + version, + }; + }); +}; + +/** + * Merge local and remote plugins + * @param localPlugins the list of local plugins + * @param remotePlugins the lost of remote plugins + * @private + */ +// eslint-disable-next-line import/no-unused-modules +export const _mergePlugins = ( + localPlugins: Plugin[], + remotePlugins: Plugin[], + versionedPlugins: Plugin[], +): Plugin[] => { + const deduped = remotePlugins.filter( + (r) => !localPlugins.some((l) => l.name === r.name) && !versionedPlugins.some((l) => l.name === r.name), + ); + + return [...localPlugins, ...deduped, ...versionedPlugins]; +}; + +/** + * Basic server to fetch plugins from Flex and return to the local dev-server + * @param plugins + * @param config + * @param onRemotePlugin + */ +// eslint-disable-next-line import/no-unused-modules, @typescript-eslint/explicit-module-boundary-types +export const _startServer = ( + plugins: StartServerPlugins, + config: StartServerConfig, + onRemotePlugin: OnRemotePlugins, +) => { + const responseHeaders = self._getHeaders(); + + return async (req: Request, res: Response): Promise => { + const { headers, method } = req; + + if (method === 'OPTIONS') { + res.writeHead(200, responseHeaders); + res.end(); + return; + } + if (method !== 'GET') { + res.writeHead(404, responseHeaders); + res.end('Route not found'); + return; + } + logger.debug('GET /plugins'); + + const jweToken = headers['x-flex-jwe'] as string; + const flexVersion = headers['x-flex-version'] as string; + if (!jweToken) { + res.writeHead(400, responseHeaders); + res.end('No X-Flex-JWE was provided'); + return; + } + + const hasRemotePlugin = config.remoteAll || plugins.remote.length !== 0; + const localPlugins = self._getLocalPlugins(config.port as number, plugins.local); + const versionedPlugins = self._getRemoteVersionedPlugins(plugins.versioned); + const promise: Promise = hasRemotePlugin + ? self._getRemotePlugins(jweToken, flexVersion) + : Promise.resolve([]); + + // eslint-disable-next-line consistent-return + return ( + promise + .then((remotePlugins) => { + if (config.remoteAll) { + return remotePlugins; + } + + // Check that all remote plugins inputted are valid + const notFoundPlugins = plugins.remote.filter((plgin) => !remotePlugins.find((r) => r.name === plgin)); + if (notFoundPlugins.length) { + remotePluginNotFound(notFoundPlugins, remotePlugins); + exit(1); + } + + // Filter and only return the ones that are in remoteInputPlugins + return remotePlugins.filter((r) => plugins.remote.includes(r.name)); + }) + // rebase will eventually get both local and remote plugins + .then((remotePlugins) => { + logger.trace('Got remote plugins', remotePlugins); + + onRemotePlugin([...versionedPlugins, ...remotePlugins]); + res.writeHead(200, responseHeaders); + res.end(JSON.stringify(self._mergePlugins(localPlugins, remotePlugins, versionedPlugins))); + }) + .catch((err) => { + res.writeHead(500, responseHeaders); + res.end(err); + }) + ); + }; +}; + +/** + * Setups up the plugin servers + * @param plugins + * @param webpackConfig + * @param serverConfig + */ +/* c8 ignore next */ +export default ( + plugins: StartServerPlugins, + webpackConfig: Configuration, + serverConfig: StartServerConfig, + onRemotePlugin: OnRemotePlugins, + pluginsConfig: PluginsConfig, +): void => { + serverConfig.port = webpackConfig.port || 3000; + + webpackConfig.proxy = plugins.local.reduce((proxy, name) => { + proxy[`/plugins/${name}.js`] = { + target: `http://127.0.0.1:${serverConfig.port}`, // placeholder + router: () => { + const match = pluginsConfig[name]; + if (!match) { + throw new Error(); + } + + return `http://127.0.0.1:${match.port}`; + }, + }; + + return proxy; + }, {}); + + webpackConfig.onBeforeSetupMiddleware = (server) => { + // @ts-ignore + serverConfig.port = server.options.port || serverConfig.port; + server?.app?.use('^/plugins$', _startServer(plugins, serverConfig, onRemotePlugin)); + }; +}; diff --git a/packages/flex-plugin-webpack5/src/devServer/webpackDevServer.ts b/packages/flex-plugin-webpack5/src/devServer/webpackDevServer.ts new file mode 100644 index 000000000..0132bc82c --- /dev/null +++ b/packages/flex-plugin-webpack5/src/devServer/webpackDevServer.ts @@ -0,0 +1,67 @@ +import WebpackDevServer, { ClientConnection, Configuration } from 'webpack-dev-server-wp5'; +import { env, logger, open, exit } from '@twilio/flex-dev-utils'; +import { getLocalAndNetworkUrls } from '@twilio/flex-dev-utils/dist/urls'; + +import { Compiler } from '../compiler'; +import { WebpackTypeWp5 } from '..'; + +const termSignals: NodeJS.Signals[] = ['SIGTERM', 'SIGINT']; + +/** + * Starts a {@link WebpackDevServer} + * @param devCompiler the {@link Compiler} compiler + * @param devConfig the dev {@link Configuration} + * @param type the {@link WebpackType} + */ +export default (devCompiler: Compiler, devConfig: Configuration, type: WebpackTypeWp5): void => { + const port = env.getPort(); + const { local } = getLocalAndNetworkUrls(port); + const isJavaScriptServer = type === WebpackTypeWp5.JavaScript; + const isStaticServer = type === WebpackTypeWp5.Static; + // @ts-ignore + const devServer = new WebpackDevServer(devConfig, devCompiler); + + if (!isStaticServer) { + // Show TS errors on browser + devCompiler.hooks.tsCompiled.tap('afterTSCompile', (warnings, errors) => { + if (warnings.length) { + devServer.sendMessage(devServer.webSocketServer?.clients as ClientConnection[], 'warnings', warnings); + } + if (errors.length) { + devServer.sendMessage(devServer.webSocketServer?.clients as ClientConnection[], 'errors', errors); + } + }); + } + + // Start the dev-server + devServer.listen(local.port, local.host, async (err) => { + if (err) { + logger.error(err); + return; + } + + const serverType = type === WebpackTypeWp5.Complete ? '' : `(${type})`; + if (isJavaScriptServer) { + logger.debug('Starting development server %s...', serverType); + } else { + logger.clearTerminal(); + logger.notice('Starting development server %s...', serverType); + } + + if (!isJavaScriptServer) { + await open(local.url); + } + }); + + // Close server and exit + const cleanUp = () => { + devServer.close(); + exit(0); + }; + + termSignals.forEach((sig) => process.on(sig, cleanUp)); + if (!env.isCI()) { + process.stdin.on('end', cleanUp); + process.stdin.resume(); + } +}; diff --git a/packages/flex-plugin-webpack5/src/index.ts b/packages/flex-plugin-webpack5/src/index.ts new file mode 100644 index 000000000..d3fdb3bff --- /dev/null +++ b/packages/flex-plugin-webpack5/src/index.ts @@ -0,0 +1,37 @@ +/* eslint-disable import/no-unused-modules */ +/* c8 ignore start */ + +import webpack from 'webpack5'; + +export enum WebpackTypeWp5 { + Static = 'static', + JavaScript = 'javascript', + Complete = 'complete', +} + +export { webpack as webpack5 }; +export { Configuration as WebpackConfigurationsWp5, Stats } from 'webpack5'; +export { Configuration as WebpackDevConfigurationsWp5 } from 'webpack-dev-server-wp5'; +export { default as webpackFactoryWp5 } from './webpack/webpack.config'; +export { default as webpackDevFactoryWp5 } from './webpack/webpack.dev'; +export { default as compilerWp5, compilerRenderer as compilerRendererWp5 } from './compiler'; +export { default as webpackDevServerWp5 } from './devServer/webpackDevServer'; +export { + default as pluginServerWp5, + Plugin as PluginWp5, + PluginsConfig as PluginsConfigWp5, + PLUGIN_INPUT_PARSER_REGEX, +} from './devServer/pluginServer'; +export { + emitCompileComplete as emitCompileCompleteWp5, + emitDevServerCrashed as emitDevServerCrashedWp5, + emitAllCompilesComplete as emitAllCompilesCompleteWp5, + IPCType as IPCTypeWp5, + onIPCServerMessage as onIPCServerMessageWp5, + OnDevServerCrashedPayload as OnDevServerCrashedPayloadWp5, + startIPCClient as startIPCClientWp5, + startIPCServer as startIPCServerWp5, +} from './devServer/ipcServer'; +export { default as DelayRenderStaticPluginWp5 } from './plugins/DelayRenderStaticPlugin'; + +/* c8 ignore stop */ diff --git a/packages/flex-plugin-webpack5/src/module.d.ts b/packages/flex-plugin-webpack5/src/module.d.ts new file mode 100644 index 000000000..72019fa92 --- /dev/null +++ b/packages/flex-plugin-webpack5/src/module.d.ts @@ -0,0 +1 @@ +declare module 'pnp-webpack-plugin'; diff --git a/packages/flex-plugin-webpack5/src/plugins/DelayRenderStaticPlugin.ts b/packages/flex-plugin-webpack5/src/plugins/DelayRenderStaticPlugin.ts new file mode 100644 index 000000000..d9d80df36 --- /dev/null +++ b/packages/flex-plugin-webpack5/src/plugins/DelayRenderStaticPlugin.ts @@ -0,0 +1,23 @@ +/* c8 ignore start */ + +import { WebpackPluginInstance, Compiler } from 'webpack5'; + +import { onIPCServerMessage, IPCType } from '../devServer/ipcServer'; + +let isCalled = false; + +export default class DelayRenderStaticPlugin implements WebpackPluginInstance { + apply(compiler: Compiler): void { + compiler.hooks.beforeCompile.tapAsync('DelayPlugin', async (_, done) => { + if (isCalled) { + done(); + } + onIPCServerMessage(IPCType.onEmitAllCompilesComplete, () => { + isCalled = true; + done(); + }); + }); + } +} + +/* c8 ignore stop */ diff --git a/packages/flex-plugin-webpack5/src/prints/devServerSuccessful.ts b/packages/flex-plugin-webpack5/src/prints/devServerSuccessful.ts new file mode 100644 index 000000000..426a1e51e --- /dev/null +++ b/packages/flex-plugin-webpack5/src/prints/devServerSuccessful.ts @@ -0,0 +1,63 @@ +import { logger } from '@twilio/flex-dev-utils'; +import { ServiceUrl } from '@twilio/flex-dev-utils/dist/urls'; +import { FlexConfigurationPlugin, readPluginsJson } from '@twilio/flex-dev-utils/dist/fs'; + +import { Plugin } from '../devServer/pluginServer'; + +/** + * Prints the success message when dev-server compiles + * @param local the local port + * @param network the local network + * @param localPlugins the list of local plugins + * @param remotePlugins the list of remote plugins + * @param hasRemote whether remote plugins are running + */ +export default ( + local: ServiceUrl, + network: ServiceUrl, + localPlugins: string[], + remotePlugins: Plugin[], + hasRemote: boolean, +): void => { + logger.success('Compiled successfully!'); + + logger.newline(); + logger.info(`Your plugin app is running in the browser on:`); + logger.newline(); + const srcs = [ + ['Local', `!!${local.url}!!`], + ['Network', `!!${network.url}!!`], + ]; + logger.columns(srcs, { indent: true }); + + if (localPlugins.length) { + logger.newline(); + logger.info('**Local Plugins:**'); + logger.newline(); + + const rows = localPlugins.map((name) => { + const plugin = readPluginsJson().plugins.find((p) => p.name === name) as FlexConfigurationPlugin; + + return [`${plugin.name}`, `!!${plugin.dir}!!`]; + }); + logger.columns(rows, { indent: true }); + } + + if (hasRemote) { + logger.newline(); + logger.info('**Remote Plugins:**'); + logger.newline(); + + const rows = remotePlugins.length + ? remotePlugins.map((p) => [`${p.name}..@..${p.version}`, `!!${p.src}!!`]) + : [['Will be displayed when you log into your Flex application']]; + + logger.columns(rows, { indent: true }); + } + + logger.newline(); + logger.info('This is a development build and is not intended to be used for production.'); + logger.info('To create a production build, use:'); + logger.newline(); + logger.installInfo('twilio', 'flex:plugins:build'); +}; diff --git a/packages/flex-plugin-webpack5/src/prints/dotEnvIncorrectVariable.ts b/packages/flex-plugin-webpack5/src/prints/dotEnvIncorrectVariable.ts new file mode 100644 index 000000000..139b8b093 --- /dev/null +++ b/packages/flex-plugin-webpack5/src/prints/dotEnvIncorrectVariable.ts @@ -0,0 +1,12 @@ +import { logger, env } from '@twilio/flex-dev-utils'; + +export default (filename: string, key: string): void => { + env.persistTerminal(); + + const isQuiet = env.isQuiet(); + env.setQuiet(false); + logger.warning( + `Unsupported variable **${key}** provided in **${filename}** file. Variables must start with either FLEX_APP_ or REACT_APP_.`, + ); + env.setQuiet(isQuiet); +}; diff --git a/packages/flex-plugin-webpack5/src/prints/index.ts b/packages/flex-plugin-webpack5/src/prints/index.ts new file mode 100644 index 000000000..ae0fd2a89 --- /dev/null +++ b/packages/flex-plugin-webpack5/src/prints/index.ts @@ -0,0 +1,3 @@ +export { default as devServerSuccessful } from './devServerSuccessful'; +export { default as remotePluginNotFound } from './remotePluginNotFound'; +export { default as dotEnvIncorrectVariable } from './dotEnvIncorrectVariable'; diff --git a/packages/flex-plugin-webpack5/src/prints/remotePluginNotFound.ts b/packages/flex-plugin-webpack5/src/prints/remotePluginNotFound.ts new file mode 100644 index 000000000..66be69099 --- /dev/null +++ b/packages/flex-plugin-webpack5/src/prints/remotePluginNotFound.ts @@ -0,0 +1,28 @@ +import { logger } from '@twilio/flex-dev-utils'; + +import { PluginWp5 } from '..'; + +/** + * Error message for when a remote plugin is not found + * + * @param notFoundPlugins name of the plugin + * @param remotePlugins array of remote plugins + */ +export default (notFoundPlugins: string[], remotePlugins: PluginWp5[]): void => { + logger.clearTerminal(); + + logger.error('Server not loading because these plugins were not found remotely:'); + logger.newline(); + for (const plugin of notFoundPlugins) { + logger.error('\t', logger.colors.bold(plugin)); + } + + logger.newline(); + logger.error('Your remote plugins are:'); + logger.newline(); + for (const plugin of remotePlugins) { + logger.info(`\t--**${plugin.name}**..@..**${plugin.version}**--`); + } + + logger.newline(); +}; diff --git a/packages/flex-plugin-webpack5/src/webpack/__tests__/clientVariables.test.ts b/packages/flex-plugin-webpack5/src/webpack/__tests__/clientVariables.test.ts new file mode 100644 index 000000000..cf446dbcf --- /dev/null +++ b/packages/flex-plugin-webpack5/src/webpack/__tests__/clientVariables.test.ts @@ -0,0 +1,145 @@ +import { env } from '@twilio/flex-dev-utils'; +import * as fs from '@twilio/flex-dev-utils/dist/fs'; +import dotenv from 'dotenv'; + +/* + * Imported directly (not via the '../../prints' barrel): TypeScript compiles barrel re-exports + * as non-configurable getters, which jest.spyOn cannot redefine. + */ +import * as dotEnvIncorrectVariableModule from '../../prints/dotEnvIncorrectVariable'; +import * as clientVariables from '../clientVariables'; + +describe('clientVariables', () => { + const processEnvName = 'process.env'; + const OLD_ENV = process.env; + const hasEnvFile = jest.fn(); + const vars = { + BAD_SECRET: 'ignored', + FLEX_APP_VAR1: 'flex-variable', + REACT_APP_VAR2: 'react-variable', + }; + const paths = { + app: { + name: 'test', + version: '1.2.3', + buildDir: 'the/build/dir', + publicDir: 'the/public/dir', + envPath: 'the/.env', + hasEnvFile, + }, + }; + const verifyVariables = (variables: Record) => { + expect(variables.FLEX_APP_VAR1).toEqual(`"${vars.FLEX_APP_VAR1}"`); + expect(variables.REACT_APP_VAR2).toEqual(`"${vars.REACT_APP_VAR2}"`); + expect(variables.BAD_SECRET).toBeUndefined(); + }; + + beforeEach(() => { + process.env = { ...OLD_ENV }; + + jest.restoreAllMocks(); + jest.resetModules(); + + // @ts-ignore + jest.spyOn(fs, 'getPaths').mockReturnValue(paths); + }); + + describe('getSanitizedProcessEnv', () => { + const profile = 'test-profile'; + + it('should only return process.env and no .env files', () => { + process.env = vars; + + jest.spyOn(clientVariables, '_readEnvFile'); + const variables = clientVariables.getSanitizedProcessEnv()[processEnvName]; + + verifyVariables(variables); + expect(clientVariables._readEnvFile).not.toHaveBeenCalled(); + }); + + it('should read .env file if provided', () => { + hasEnvFile.mockReturnValue(true); + jest.spyOn(clientVariables, '_readEnvFile').mockReturnValue(vars); + + const variables = clientVariables.getSanitizedProcessEnv()[processEnvName]; + verifyVariables(variables); + expect(clientVariables._readEnvFile).toHaveBeenCalledTimes(1); + expect(clientVariables._readEnvFile).toHaveBeenCalledWith('.env', paths.app.envPath); + }); + + it('should not read profile.env if profile is provided but no file found', () => { + hasEnvFile.mockReturnValue(false); + jest.spyOn(env, 'getTwilioProfile').mockReturnValue(profile); + jest.spyOn(fs, 'resolveRelative').mockReturnValue(`/.${profile}.env`); + jest.spyOn(fs, 'checkAFileExists').mockReturnValue(false); + jest.spyOn(clientVariables, '_readEnvFile'); + + clientVariables.getSanitizedProcessEnv(); + expect(clientVariables._readEnvFile).not.toHaveBeenCalled(); + expect(fs.checkAFileExists).toHaveBeenCalled(); + }); + + it('should read profile.env ', () => { + hasEnvFile.mockReturnValue(false); + jest.spyOn(env, 'getTwilioProfile').mockReturnValue(profile); + jest.spyOn(fs, 'checkAFileExists').mockReturnValue(true); + jest.spyOn(fs, 'resolveRelative').mockReturnValue(`/.${profile}.env`); + jest.spyOn(clientVariables, '_readEnvFile').mockReturnValue(vars); + + const variables = clientVariables.getSanitizedProcessEnv()[processEnvName]; + verifyVariables(variables); + expect(clientVariables._readEnvFile).toHaveBeenCalledTimes(1); + expect(clientVariables._readEnvFile).toHaveBeenCalledWith(`.${profile}.env`, `/.${profile}.env`); + }); + + it('should overwrite .env by profile.env duplicate and keep all', () => { + const envVars = { + FLEX_APP_VAR_REPLACE: 'original', + FLEX_APP_ANOTHER: 'another', + }; + const profileVars = { + FLEX_APP_VAR_REPLACE: 'replaced', + FLEX_APP_VAR: 'var', + }; + jest.spyOn(env, 'getTwilioProfile').mockReturnValue(profile); + hasEnvFile.mockReturnValue(true); + jest.spyOn(fs, 'checkAFileExists').mockReturnValue(true); + jest.spyOn(fs, 'resolveRelative').mockReturnValue(`/.${profile}.env`); + jest.spyOn(clientVariables, '_readEnvFile').mockImplementation((filename) => { + if (filename === '.env') { + return envVars; + } + + return profileVars; + }); + + const variables = clientVariables.getSanitizedProcessEnv()[processEnvName]; + expect(variables.FLEX_APP_VAR_REPLACE).toEqual('"replaced"'); + expect(variables.FLEX_APP_ANOTHER).toEqual(`"${envVars.FLEX_APP_ANOTHER}"`); + expect(variables.FLEX_APP_VAR).toEqual(`"${profileVars.FLEX_APP_VAR}"`); + }); + }); + + describe('_filterVariables', () => { + it('should filter variables', () => { + const variables = clientVariables._filterVariables(vars); + + verifyVariables(variables); + }); + }); + + describe('_readEnvFile', () => { + it('should parse file and log warning', () => { + jest.spyOn(dotenv, 'parse').mockReturnValue(vars); + jest.spyOn(dotEnvIncorrectVariableModule, 'default').mockReturnThis(); + jest.spyOn(fs, 'readFileSync').mockReturnValue('data'); + const variables = clientVariables._readEnvFile('.env', 'the/path'); + + expect(variables.FLEX_APP_VAR1).toEqual(vars.FLEX_APP_VAR1); + expect(variables.REACT_APP_VAR2).toEqual(vars.REACT_APP_VAR2); + expect(variables.BAD_SECRET).toEqual(vars.BAD_SECRET); + expect(dotEnvIncorrectVariableModule.default).toHaveBeenCalledTimes(1); + expect(dotEnvIncorrectVariableModule.default).toHaveBeenCalledWith('.env', 'BAD_SECRET'); + }); + }); +}); diff --git a/packages/flex-plugin-webpack5/src/webpack/__tests__/webpack.config.test.ts b/packages/flex-plugin-webpack5/src/webpack/__tests__/webpack.config.test.ts new file mode 100644 index 000000000..5ebb9a03e --- /dev/null +++ b/packages/flex-plugin-webpack5/src/webpack/__tests__/webpack.config.test.ts @@ -0,0 +1,272 @@ +import * as webpack from 'webpack5'; +import { Environment } from '@twilio/flex-dev-utils/dist/env'; +import * as fs from '@twilio/flex-dev-utils/dist/fs'; + +import * as webpackConfig from '../webpack.config'; +import * as clientVariables from '../clientVariables'; +import { WebpackTypeWp5 } from '../..'; + +jest.mock('@twilio/flex-dev-utils/dist/fs'); +jest.mock('webpack5/lib/DefinePlugin'); + +describe('WebpackConfiguration', () => { + const isTSProject = jest.fn(); + const hasEnvFile = jest.fn(); + const hasEnvExampleFile = jest.fn(); + const hasEnvDefaultsPath = jest.fn(); + const paths = { + webpack: { + nodeModulesDir: 'webpack/node_modules', + }, + app: { + name: 'test', + version: '1.2.3', + buildDir: 'the/build/dir', + publicDir: 'the/public/dir', + isTSProject, + hasEnvFile, + hasEnvExampleFile, + hasEnvDefaultsPath, + }, + extensions: [], + scripts: { + nodeModulesDir: 'the/scripts/node_modules', + }, + cli: { + nodeModulesDir: 'cli/node_modules', + }, + }; + const OLD_ENV = { ...process.env }; + + beforeEach(() => { + jest.restoreAllMocks(); + jest.resetModules(); + process.env = { ...OLD_ENV }; + + // @ts-ignore + jest.spyOn(fs, 'getPaths').mockReturnValue(paths); + }); + + describe('default', () => { + it('should get static config', () => { + const _getBase = jest.spyOn(webpackConfig, '_getBase').mockReturnThis(); + const _getStaticConfiguration = jest.spyOn(webpackConfig, '_getStaticConfiguration').mockReturnThis(); + const _getJavaScriptConfiguration = jest.spyOn(webpackConfig, '_getJavaScriptConfiguration').mockReturnThis(); + + webpackConfig.default(Environment.Development, WebpackTypeWp5.Static); + + expect(_getBase).toHaveBeenCalledTimes(1); + expect(_getStaticConfiguration).toHaveBeenCalledTimes(1); + expect(_getJavaScriptConfiguration).not.toHaveBeenCalled(); + }); + + it('should get js config', () => { + const _getBase = jest.spyOn(webpackConfig, '_getBase').mockReturnThis(); + const _getStaticConfiguration = jest.spyOn(webpackConfig, '_getStaticConfiguration').mockReturnThis(); + const _getJavaScriptConfiguration = jest.spyOn(webpackConfig, '_getJavaScriptConfiguration').mockReturnThis(); + + webpackConfig.default(Environment.Development, WebpackTypeWp5.JavaScript); + + expect(_getBase).toHaveBeenCalledTimes(1); + expect(_getStaticConfiguration).not.toHaveBeenCalled(); + expect(_getJavaScriptConfiguration).toHaveBeenCalledTimes(1); + }); + + it('should get all config', () => { + const _getBase = jest.spyOn(webpackConfig, '_getBase').mockReturnThis(); + const _getStaticConfiguration = jest.spyOn(webpackConfig, '_getStaticConfiguration').mockReturnThis(); + const _getJavaScriptConfiguration = jest.spyOn(webpackConfig, '_getJavaScriptConfiguration').mockReturnThis(); + + webpackConfig.default(Environment.Development, WebpackTypeWp5.Complete); + + expect(_getBase).toHaveBeenCalledTimes(1); + expect(_getStaticConfiguration).toHaveBeenCalledTimes(1); + expect(_getJavaScriptConfiguration).toHaveBeenCalledTimes(1); + }); + }); + + describe('_getJavaScriptConfiguration', () => { + it('should test devtool field', () => { + jest.spyOn(webpackConfig, '_getJavaScriptEntries').mockReturnValue([]); + jest.spyOn(webpackConfig, '_getOptimization').mockReturnValue({ + splitChunks: false, + runtimeChunk: false, + minimize: false, + minimizer: [], + }); + jest.spyOn(webpackConfig, '_getJSPlugins').mockReturnValue([]); + + const configProd = webpackConfig._getJavaScriptConfiguration({}, Environment.Production); + const configDev = webpackConfig._getJavaScriptConfiguration({}, Environment.Development); + + expect(configProd.devtool).toEqual('cheap-source-map'); + expect(configDev.devtool).toEqual('source-map'); + }); + + it('should get production config', () => { + const _getJavaScriptEntries = jest.spyOn(webpackConfig, '_getJavaScriptEntries').mockReturnValue([]); + const _getOptimization = jest.spyOn(webpackConfig, '_getOptimization').mockReturnValue({ + splitChunks: false, + runtimeChunk: false, + minimize: false, + minimizer: [], + }); + const _getJSPlugins = jest.spyOn(webpackConfig, '_getJSPlugins').mockReturnValue([]); + + const config = webpackConfig._getJavaScriptConfiguration({}, Environment.Production); + const { output } = config; + + expect(output?.path).toEqual(paths.app.buildDir); + expect(output?.filename).toEqual(`${paths.app.name}.js`); + expect(output?.publicPath).toEqual('/'); + expect(output?.pathinfo).toEqual(false); + expect(config.bail).toEqual(true); + + expect(_getJavaScriptEntries).toHaveBeenCalledTimes(1); + expect(_getOptimization).toHaveBeenCalledTimes(1); + expect(_getJSPlugins).toHaveBeenCalledTimes(1); + }); + + it('should get development config', () => { + const _getJavaScriptEntries = jest.spyOn(webpackConfig, '_getJavaScriptEntries').mockReturnValue([]); + const _getOptimization = jest.spyOn(webpackConfig, '_getOptimization').mockReturnValue({ + splitChunks: false, + runtimeChunk: false, + minimize: false, + minimizer: [], + }); + const _getJSPlugins = jest.spyOn(webpackConfig, '_getJSPlugins').mockReturnValue([]); + + const config = webpackConfig._getJavaScriptConfiguration({}, Environment.Development); + const { output } = config; + + expect(output?.path).toEqual(paths.app.buildDir); + expect(output?.filename).toEqual(`plugins/${paths.app.name}.js`); + expect(output?.publicPath).toEqual('/'); + expect(output?.pathinfo).toEqual(true); + expect(config.bail).toEqual(false); + + expect(_getJavaScriptEntries).toHaveBeenCalledTimes(1); + expect(_getOptimization).toHaveBeenCalledTimes(1); + expect(_getJSPlugins).toHaveBeenCalledTimes(1); + }); + }); + + describe('_getJSScripts', () => { + it('should return flex-ui only', () => { + const scripts = webpackConfig._getJSScripts('1.18.0', '', ''); + + expect(scripts).toHaveLength(1); + expect(scripts[0]).toContain('flex-ui'); + expect(scripts[0]).toContain('1.18.0'); + expect(scripts[0]).toContain('twilio-flex.min.js'); + }); + + it('should return flex-ui and react/dom', () => { + const scripts = webpackConfig._getJSScripts('1.19.0', '16.13.1', '16.12.1'); + + expect(scripts).toHaveLength(3); + expect(scripts[0]).toContain('umd/react.development'); + expect(scripts[0]).toContain('16.13.1'); + expect(scripts[1]).toContain('umd/react-dom.development'); + expect(scripts[1]).toContain('16.12.1'); + expect(scripts[2]).toContain('flex-ui'); + expect(scripts[2]).toContain('1.19.0'); + expect(scripts[2]).toContain('twilio-flex.unbundled-react.min.js'); + }); + + it('should overwrite flex-ui if --flex-ui-source is provided', () => { + process.env.FLEX_UI_SRC = 'http://localhost:8080/twilio-flex-ui.dev.browser.js'; + const scripts = webpackConfig._getJSScripts('1.19.0', '16.13.1', '16.12.1'); + + expect(scripts).toHaveLength(3); + expect(scripts[0]).toContain('umd/react.development'); + expect(scripts[0]).toContain('16.13.1'); + expect(scripts[1]).toContain('umd/react-dom.development'); + expect(scripts[1]).toContain('16.12.1'); + expect(scripts[2]).toContain('localhost:8080'); + }); + + it('should overwrite flex-ui even if flex-ui is < 1.19.0', () => { + process.env.FLEX_UI_SRC = 'http://localhost:8080/twilio-flex-ui.dev.browser.js'; + const scripts = webpackConfig._getJSScripts('1.18.0', '', ''); + + expect(scripts).toHaveLength(1); + expect(scripts[0]).toContain('localhost:8080'); + }); + }); + + describe('_getBasePlugins', () => { + const depVersions = { + '@twilio/flex-plugin': '1.1.0', + '@twilio/flex-ui': '1.2.0', + react: '1.3.0', + 'react-dom': '1.4.0', + }; + + const mockGetDependencyVersion = () => { + jest.spyOn(fs, 'getDependencyVersion').mockImplementation((name) => depVersions[name]); + }; + const verifyInternalDefinition = () => { + expect(webpack.DefinePlugin).toHaveBeenCalledWith( + expect.objectContaining({ + __FPB_PLUGIN_UNIQUE_NAME: `'${paths.app.name}'`, + __FPB_PLUGIN_VERSION: `'${paths.app.version}'`, + __FPB_FLEX_PLUGIN_VERSION: `'${depVersions['@twilio/flex-plugin']}'`, + __FPB_FLEX_UI_VERSION: `'${depVersions['@twilio/flex-ui']}'`, + __FPB_REACT_VERSION: `'${depVersions.react}'`, + __FPB_REACT_DOM_VERSION: `'${depVersions['react-dom']}'`, + __FPB_CRACO_CONFIG_FLEX_PLUGIN_VERSION: `'N/A'`, + }), + ); + }; + + beforeEach(() => { + // @ts-ignore + webpack.DefinePlugin.mockReset(); + }); + + it('should call DefinePlugin for internal definitions', () => { + mockGetDependencyVersion(); + const plugins = webpackConfig._getBasePlugins(Environment.Development); + + expect(webpack.DefinePlugin).toHaveBeenCalledTimes(1); + verifyInternalDefinition(); + + const plugin = plugins.find((p) => p.constructor.name === webpack.DefinePlugin.name); + expect(plugin).toBeDefined(); + }); + + it('should add client variables', () => { + const variables = { + sample: 'variable', + test: 'name', + }; + mockGetDependencyVersion(); + jest.spyOn(clientVariables, 'getSanitizedProcessEnv').mockReturnValue({ 'process.env': variables }); + + const plugins = webpackConfig._getBasePlugins(Environment.Development); + + expect(webpack.DefinePlugin).toHaveBeenCalledTimes(1); + expect(webpack.DefinePlugin).toHaveBeenCalledWith( + expect.objectContaining({ + 'process.env': variables, + }), + ); + verifyInternalDefinition(); + + const plugin = plugins.find((p) => p.constructor.name === webpack.DefinePlugin.name); + expect(plugin).toBeDefined(); + }); + }); + + describe('_getStaticConfiguration', () => { + it('should add static plugins', () => { + jest.spyOn(webpackConfig, '_getStaticPlugins').mockReturnValue([]); + webpackConfig._getStaticConfiguration({}, Environment.Development); + + expect(webpackConfig._getStaticPlugins).toHaveBeenCalledTimes(1); + expect(webpackConfig._getStaticPlugins).toHaveBeenCalledWith(Environment.Development); + }); + }); +}); diff --git a/packages/flex-plugin-webpack5/src/webpack/clientVariables.ts b/packages/flex-plugin-webpack5/src/webpack/clientVariables.ts new file mode 100644 index 000000000..472ec381e --- /dev/null +++ b/packages/flex-plugin-webpack5/src/webpack/clientVariables.ts @@ -0,0 +1,82 @@ +import dotenv from 'dotenv'; +import { readFileSync, getPaths, resolveRelative, checkAFileExists } from '@twilio/flex-dev-utils/dist/fs'; +import { env } from '@twilio/flex-dev-utils'; + +import { dotEnvIncorrectVariable } from '../prints'; +/* + * Self-import so getSanitizedProcessEnv's call to _readEnvFile goes through the (spy-able) + * module namespace rather than a fixed local binding - lets jest.spyOn intercept it in tests. + */ +// eslint-disable-next-line import/no-self-import +import * as self from './clientVariables'; + +type CodeValueObject = { + [key: string]: any; +}; +type ProcessEnv = { + [key: string]: string | undefined; +}; +interface SanitizedProcessEnv { + 'process.env': CodeValueObject; +} + +const REACT_APP_REGEX = /^REACT_APP_/i; +const FLEX_APP_REGEX = /^FLEX_APP_/i; + +/** + * Checks whether the variable is of correct format + * @param key + */ +const isValid = (key: string): boolean => FLEX_APP_REGEX.test(key) || REACT_APP_REGEX.test(key); + +/** + * Reads the .env file and process it. It will print warning messages if the format is invalid + * @param filename the filename to read + * @param path the path to the file + */ +export const _readEnvFile = (filename: string, path: string): ProcessEnv => { + const newVars = dotenv.parse(readFileSync(path)); + Object.keys(newVars) + .filter((key: string) => !isValid(key)) + .forEach((key: string) => dotEnvIncorrectVariable(filename, key)); + + return newVars; +}; + +/** + * Filters and sanitizes the variables + * @param variables the variables to read + */ +export const _filterVariables = (variables: CodeValueObject): CodeValueObject => { + return Object.keys(variables) + .filter(isValid) + .reduce((newEnvs: CodeValueObject, key: string) => { + newEnvs[key] = JSON.stringify(variables[key]); + return newEnvs; + }, {}); +}; + +/** + * Reads the .env files and sanitizes and only returns allowed keys + */ +export const getSanitizedProcessEnv = (): SanitizedProcessEnv => { + const { app: appPaths, cwd } = getPaths(); + let { env: variables } = process; + + // Support .env file if provided + if (appPaths.hasEnvFile()) { + variables = { ...variables, ...self._readEnvFile('.env', appPaths.envPath) }; + } + // Support for profile specific .env file (this should come after .env to allow overwrite) + if (env.getTwilioProfile()) { + const filename = `.${env.getTwilioProfile()}.env`; + const profileEnvPath = resolveRelative(cwd, `/${filename}`); + if (checkAFileExists(profileEnvPath)) { + variables = { ...variables, ...self._readEnvFile(filename, profileEnvPath) }; + } + } + + return { + 'process.env': _filterVariables(variables), + }; +}; diff --git a/packages/flex-plugin-webpack5/src/webpack/pnpTs.ts b/packages/flex-plugin-webpack5/src/webpack/pnpTs.ts new file mode 100644 index 000000000..da86dd083 --- /dev/null +++ b/packages/flex-plugin-webpack5/src/webpack/pnpTs.ts @@ -0,0 +1,40 @@ +/* c8 ignore start */ +/* eslint-disable import/no-unused-modules, @typescript-eslint/explicit-module-boundary-types */ +import { CompilerOptions, ModuleResolutionHost, ResolvedModuleWithFailedLookupLocations } from 'typescript'; +import { resolveModuleName as resolver } from 'ts-pnp'; + +/** + * This is taken from https://github.com/TypeStrong/fork-ts-checker-webpack-plugin documentation + */ + +// Taken from 'ts-pnp'; this is not exported as a type itself +interface TS { + resolveModuleName: ( + moduleName: string, + containingFile: string, + options: CompilerOptions, + moduleResolutionHost: ResolvedModuleWithFailedLookupLocations, + ) => ResolvedModuleWithFailedLookupLocations; +} + +export const resolveModuleName = ( + typescript: TS, + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + resolutionHost: ModuleResolutionHost, +) => { + return resolver(moduleName, containingFile, compilerOptions, resolutionHost, typescript.resolveModuleName); +}; + +export const resolveTypeReferenceDirective = ( + typescript: TS, + moduleName: string, + containingFile: string, + compilerOptions: CompilerOptions, + resolutionHost: ModuleResolutionHost, +) => { + return resolver(moduleName, containingFile, compilerOptions, resolutionHost, typescript.resolveModuleName); +}; + +/* c8 ignore stop */ diff --git a/packages/flex-plugin-webpack5/src/webpack/webpack.config.ts b/packages/flex-plugin-webpack5/src/webpack/webpack.config.ts new file mode 100644 index 000000000..c670ec6d9 --- /dev/null +++ b/packages/flex-plugin-webpack5/src/webpack/webpack.config.ts @@ -0,0 +1,584 @@ +/* eslint-disable global-require, @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires */ +/// + +import ModuleScopePlugin from '@k88/module-scope-plugin'; +import { semver, env } from '@twilio/flex-dev-utils'; +import { Environment } from '@twilio/flex-dev-utils/dist/env'; +import fs, { getDependencyVersion, getPaths, resolveModulePath } from '@twilio/flex-dev-utils/dist/fs'; +import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin'; +import HtmlWebpackPlugin from 'html-webpack-plugin-wp5'; +import PnpWebpackPlugin from 'pnp-webpack-plugin'; +import TerserPlugin from 'terser-webpack-plugin-wp5'; +import { + Configuration, + DefinePlugin, + HotModuleReplacementPlugin, + RuleSetRule, + RuleSetUseItem, + WebpackPluginInstance, + SourceMapDevToolPlugin, + ResolveOptions, +} from 'webpack5'; +import { template } from 'lodash'; + +import { getSanitizedProcessEnv } from './clientVariables'; +import { WebpackTypeWp5 } from '..'; +/* + * Self-import so internal calls between these exports go through the (spy-able) module + * namespace rather than a fixed local binding - lets jest.spyOn intercept same-module calls in tests. + */ +// eslint-disable-next-line import/no-self-import +import * as self from './webpack.config'; + +interface LoaderOption { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + [name: string]: any; +} + +/** + * Resolves the `typescript` module to use for type-checking a plugin project. + * + * `resolveModulePath('typescript')` resolves relative to this package's own installation + * (it only ever falls back to other paths if the bare `require.resolve` throws, which it + * never does here since this package always has some version of `typescript` available). + * That means, unpatched, every plugin gets type-checked against whatever TypeScript version + * this package happens to be built with, regardless of what the plugin itself declares and + * has installed - silently ignoring newer syntax the plugin's own TypeScript could parse fine. + * Prefer the plugin project's own installed `typescript`, and only fall back to this + * package's copy if the plugin has none. + * @private + */ +export const _resolveProjectTypescriptPath = (): string | false => { + try { + return require.resolve('typescript', { paths: [getPaths().app.nodeModulesDir] }); + } catch { + return resolveModulePath('typescript'); + } +}; + +/* + * interface Optimization { + * splitChunks?: false; + * runtimeChunk: boolean; + * minimize: boolean; + * minimizer: WebpackPluginInstance; + * } + */ + +const IMAGE_SIZE_BYTE = 10 * 1024; +const FLEX_SHIM = '@twilio/flex-plugin-scripts/dev_assets/flex-shim.js'; +const EXTERNALS = { + react: 'React', + 'react-dom': 'ReactDOM', + redux: 'Redux', + 'react-redux': 'ReactRedux', +}; + +/** + * Returns the JS scripts to inject into the index.html file + * @param flexUIVersion the flex-ui version + * @param reactVersion the react version + * @param reactDOMVersion the react-dom version + */ +export const _getJSScripts = (flexUIVersion: string, reactVersion: string, reactDOMVersion: string): string[] => { + const envSrc = env.getFlexUISrc(); + if (!semver.satisfies(flexUIVersion, '>=1.19.0')) { + if (envSrc) { + return [``]; + } + + return [ + ``, + ]; + } + + const flexUISrc = + envSrc || `https://assets.flex.twilio.com/releases/flex-ui/${flexUIVersion}/twilio-flex.unbundled-react.min.js`; + + return [ + ``, + ``, + ``, + ]; +}; + +/** + * Returns the Babel Loader configuration + * @param isProd whether this is a production build + */ +/* c8 ignore next */ +const _getBabelLoader = (isProd: boolean) => ({ + test: new RegExp(`\.(${getPaths().extensions.join('|')})$`), + include: getPaths().app.srcDir, + loader: require.resolve('babel-loader'), + options: { + customize: require.resolve('babel-preset-react-app/webpack-overrides'), + babelrc: false, + configFile: false, + presets: [ + require.resolve('@babel/preset-react'), + require.resolve('@babel/preset-env'), + require.resolve('@babel/preset-typescript'), + ], + plugins: [ + [ + require.resolve('babel-plugin-named-asset-import'), + { + loaderMap: { + svg: { ReactComponent: '@svgr/webpack?-svgo,+titleProp,+ref![path]' }, + }, + }, + ], + ], + compact: isProd, + }, +}); + +/** + * Gets the image loader + * @private + */ +/* c8 ignore next */ +const _getImageLoader = (): RuleSetRule => ({ + test: [/\.bmp$/, /\.gif$/, /\.jpe?g$/, /\.png$/], + loader: require.resolve('url-loader'), + options: { + limit: IMAGE_SIZE_BYTE, + }, +}); + +/** + * Gets the styles loader + * @param isProd whether this is a production build + * @private + */ +const _getStyleLoaders = (isProd: boolean): RuleSetRule[] => { + /** + * Gets the loader for the given style + * @param options the options + * @param preProcessor the pre-processor, for example scss-loader + * @param implementation the implementation for thr scss-loader + */ + const getStyleLoader = (options: LoaderOption, preProcessor?: string, implementation?: string) => { + const loaders: RuleSetUseItem[] = []; + + // Main style loader to work when compiled + loaders.push(require.resolve('style-loader')); + + // All css loader + loaders.push( + { + loader: require.resolve('css-loader'), + options, + }, + { + loader: require.resolve('postcss-loader'), + options: { + postcssOptions: { + plugins: () => [ + require('postcss-flexbugs-fixes'), + require('postcss-preset-env')({ + autoprefixer: { + flexbox: 'no-2009', + }, + stage: 3, + }), + ], + }, + sourceMap: isProd, + }, + }, + ); + + // Add a pre-processor loader (converting SCSS to CSS) + if (preProcessor) { + const preProcessorOptions: Record = { + sourceMap: isProd, + }; + + if (implementation) { + const nodePath = resolveModulePath(implementation); + if (nodePath) { + preProcessorOptions.implementation = require(nodePath); + } + } + + loaders.push( + { + loader: require.resolve('resolve-url-loader'), + options: { + sourceMap: isProd, + }, + }, + { + loader: require.resolve(preProcessor), + options: preProcessorOptions, + }, + ); + } + + return loaders; + }; + + return [ + { + test: /\.css$/, + exclude: /\.module\.css$/, + use: getStyleLoader({ + importLoaders: 1, + sourceMap: isProd, + }), + sideEffects: true, + }, + { + test: /\.module\.css$/, + use: getStyleLoader({ + importLoaders: 1, + sourceMap: isProd, + modules: true, + }), + }, + { + test: /\.(scss|sass)$/, + exclude: /\.module\.(scss|sass)$/, + use: getStyleLoader( + { + importLoaders: 3, + sourceMap: isProd, + }, + 'sass-loader', + 'node-sass', + ), + sideEffects: true, + }, + { + test: /\.module\.(scss|sass)$/, + use: getStyleLoader( + { + importLoaders: 3, + sourceMap: isProd, + modules: true, + }, + 'sass-loader', + 'node-sass', + ), + }, + ]; +}; + +/** + * Returns an array of {@link Plugin} for Webpack + * @param environment the environment + * @private + */ +export const _getBasePlugins = (environment: Environment) => { + const plugins: WebpackPluginInstance[] = []; + + const flexUIVersion = getDependencyVersion('@twilio/flex-ui'); + const reactVersion = getDependencyVersion('react'); + const reactDOMVersion = getDependencyVersion('react-dom'); + + const defined = { + __FPB_PLUGIN_UNIQUE_NAME: `'${getPaths().app.name}'`, + __FPB_PLUGIN_VERSION: `'${getPaths().app.version}'`, + __FPB_FLEX_PLUGIN_VERSION: `'${getDependencyVersion('@twilio/flex-plugin')}'`, + __FPB_FLEX_UI_VERSION: `'${flexUIVersion}'`, + __FPB_REACT_VERSION: `'${reactVersion}'`, + __FPB_REACT_DOM_VERSION: `'${reactDOMVersion}'`, + // backward compatibility with v3 + __FPB_CRACO_CONFIG_FLEX_PLUGIN_VERSION: `'N/A'`, + }; + + // The @k88/cra-webpack-hot-dev-client package requires these environment variables to be replaced + if (environment === Environment.Development) { + if (env.getWDSSocketHost()) { + defined['process.env.WDS_SOCKET_HOST'] = env.getWDSSocketHost(); + } + if (env.getWDSSocketPath()) { + defined['process.env.WDS_SOCKET_PATH'] = env.getWDSSocketPath(); + } + if (env.getWDSSocketPort()) { + defined['process.env.WDS_SOCKET_PORT'] = env.getWDSSocketPort(); + } + } + + plugins.push(new DefinePlugin({ ...defined, ...getSanitizedProcessEnv() })); + + return plugins; +}; + +/** + * Returns an array of {@link Plugin} for Webpack Static + * @param environment + */ +export const _getStaticPlugins = (environment: Environment) => { + const plugins: WebpackPluginInstance[] = []; + const { dependencies } = getPaths().app; + + // index.html entry point + if (environment === Environment.Development) { + plugins.push(new HotModuleReplacementPlugin()); + plugins.push( + new HtmlWebpackPlugin({ + inject: false, // Preventing automatic injection + templateContent: () => { + let content = fs.readFileSync(getPaths().scripts.indexHTMLPath, 'utf8'); + // Ensure Webpack 5 expected syntax is in place + content = content.replace('%__FPB_JS_SCRIPTS%', '<%= __FPB_JS_SCRIPTS %>'); + // Manually process the EJS template using lodash.template + return template(content)({ + __FPB_JS_SCRIPTS: _getJSScripts( + dependencies.flexUI.version, + dependencies.react.version, + dependencies.reactDom.version, + ).join('\n'), + }); + }, + }) as unknown as WebpackPluginInstance, + ); + } + + return plugins; +}; + +/** + * Returns an array of {@link Plugin} for Webpack Javascript + * @param environment + */ +export const _getJSPlugins = (environment: Environment) => { + const plugins: WebpackPluginInstance[] = []; + const isDev = environment === Environment.Development; + const isProd = environment === Environment.Production; + + if (isProd) { + plugins.push( + new SourceMapDevToolPlugin({ + filename: `${getPaths().app.name}.js.map`, + module: false, + append: '\n//# sourceMappingURL=bundle.js.map', + }), + ); + } + if (getPaths().app.isTSProject()) { + const typescriptPath = _resolveProjectTypescriptPath(); + /* + * Type of the constructor options for the currently installed fork-ts-checker-webpack-plugin, + * avoids depending on a type export the package doesn't provide at its root. + */ + type Options = ConstructorParameters[0]; + const config: Options = { + async: isDev, + typescript: { + typescriptPath: typescriptPath || undefined, + configFile: getPaths().app.tsConfigPath, + diagnosticOptions: { + syntactic: true, + semantic: true, + declaration: false, + global: false, + }, + }, + issue: { + include: [{ file: '**' }], + exclude: [ + { file: '**/__tests__/**' }, + { file: '**/__mocks__/**' }, + { file: '**/?(*.)(spec|test).*' }, + { file: '**/src/setupProxy.*' }, + { file: '**/src/setupTests.*' }, + ], + }, + formatter: isProd ? 'codeframe' : 'basic', + logger: 'webpack-infrastructure', + }; + + /* + * fork-ts-checker-webpack-plugin resolves its own nested copy of the `webpack` peer dependency, + * which TypeScript sees as a distinct (though compatible) Compiler type from our own webpack5 import. + */ + plugins.push(new ForkTsCheckerWebpackPlugin(config) as unknown as WebpackPluginInstance); + } + + return plugins; +}; + +/** + * Returns the `entry` key of the webpack + * @private + */ +export const _getJavaScriptEntries = (): string[] => { + const entry: string[] = []; + entry.push(getPaths().app.entryPath); + + return entry; +}; + +/** + * Returns the `optimization` key of webpack + * @param environment the environment + * @private + */ +/* c8 ignore next */ +export const _getOptimization = (environment: Environment): any => { + const isProd = environment === Environment.Production; + return { + splitChunks: false, + runtimeChunk: false, + minimize: isProd, + minimizer: [ + new TerserPlugin({ + terserOptions: { + parse: { + ecma: 2017, + }, + compress: { + ecma: 5, + comparisons: false, + inline: 2, + }, + mangle: { + safari10: true, + }, + // eslint-disable-next-line camelcase + keep_classnames: isProd, + // eslint-disable-next-line camelcase + keep_fnames: isProd, + output: { + ecma: 5, + comments: false, + // eslint-disable-next-line camelcase + ascii_only: true, + }, + sourceMap: isProd, + }, + }), + ], + }; +}; + +/** + * Returns the `resolve` key of webpack + * @param environment the environment + * @private + */ +const _getResolve = (environment: Environment) => { + const isProd = environment === Environment.Production; + const extensions = getPaths().app.isTSProject() + ? getPaths().extensions + : getPaths().extensions.filter((e) => !e.includes('ts')); + + const paths = getPaths(); + + const resolve: ResolveOptions = { + modules: [ + 'node_modules', + paths.app.nodeModulesDir, + paths.scripts.nodeModulesDir, + paths.webpack.nodeModulesDir, + paths.cli.nodeModulesDir, + ], + extensions: extensions.map((e) => `.${e}`), + alias: { + '@twilio/flex-ui': FLEX_SHIM, + }, + plugins: [PnpWebpackPlugin, new ModuleScopePlugin(paths.app.srcDir, [paths.app.pkgPath])], + }; + + if (isProd && resolve.alias) { + resolve.alias['scheduler/tracing'] = 'scheduler/tracing-profiling'; + } + + return resolve; +}; + +/** + * Returns the base {@link Configuration} + * @private + */ +export const _getBase = (environment: Environment): Configuration => { + const isProd = environment === Environment.Production; + const config: Configuration = { + resolve: _getResolve(environment), + resolveLoader: { + plugins: [PnpWebpackPlugin.moduleLoader(module)], + }, + externals: EXTERNALS, + module: { + strictExportPresence: true, + rules: [ + { + oneOf: [_getImageLoader(), _getBabelLoader(isProd), ..._getStyleLoaders(isProd)], + }, + ], + }, + plugins: _getBasePlugins(environment), + }; + config.mode = isProd ? Environment.Production : Environment.Development; + + config.entry = []; + if (environment === Environment.Development) { + config.entry.push(require.resolve('@k88/cra-webpack-hot-dev-client/build')); + } + + return config; +}; + +/** + * Returns the {@link Configuration} for static type + * @private + */ +export const _getStaticConfiguration = (config: Configuration, environment: Environment): Configuration => { + config.plugins = config.plugins ? config.plugins : []; + config.plugins.push(...self._getStaticPlugins(environment)); + + return config; +}; + +/** + * Returns the {@link Configuration} for JS type + * @private + */ +export const _getJavaScriptConfiguration = (config: Configuration, environment: Environment): Configuration => { + const isProd = environment === Environment.Production; + const filename = `${getPaths().app.name}`; + const outputName = environment === Environment.Production ? filename : `plugins/${filename}`; + + config.entry = config.entry ? config.entry : []; + config.plugins = config.plugins ? config.plugins : []; + + // @ts-ignore + config.entry.push(...self._getJavaScriptEntries()); + config.output = { + path: getPaths().app.buildDir, + pathinfo: !isProd, + filename: `${outputName}.js`, + sourceMapFilename: `${outputName}.[contenthash].js.map`, + publicPath: '/', + globalObject: 'this', + }; + config.bail = isProd; + config.devtool = isProd ? 'cheap-source-map' : 'source-map'; + config.optimization = self._getOptimization(environment); + config.node = false; + config.plugins.push(...self._getJSPlugins(environment)); + + return config; +}; + +/** + * Main method for generating a webpack configuration + * @param environment + * @param type + */ +export default (environment: Environment, type: WebpackTypeWp5): Configuration => { + const config = self._getBase(environment); + + if (type === WebpackTypeWp5.Static) { + return self._getStaticConfiguration(config, environment); + } + if (type === WebpackTypeWp5.JavaScript) { + return self._getJavaScriptConfiguration(config, environment); + } + + return self._getJavaScriptConfiguration(self._getStaticConfiguration(config, environment), environment); +}; diff --git a/packages/flex-plugin-webpack5/src/webpack/webpack.dev.ts b/packages/flex-plugin-webpack5/src/webpack/webpack.dev.ts new file mode 100644 index 000000000..0f8ed1030 --- /dev/null +++ b/packages/flex-plugin-webpack5/src/webpack/webpack.dev.ts @@ -0,0 +1,82 @@ +import { env } from '@twilio/flex-dev-utils'; +import { getLocalAndNetworkUrls } from '@twilio/flex-dev-utils/dist/urls'; +import { ClientConfiguration, Configuration, Static } from 'webpack-dev-server-wp5'; +import { getPaths } from '@twilio/flex-dev-utils/dist/fs'; + +import { WebpackTypeWp5 } from '..'; + +/** + * Returns the base {@link Configuration} + * @private + */ +// eslint-disable-next-line import/no-unused-modules +export const _getBase = (): Configuration => { + const { local } = getLocalAndNetworkUrls(env.getPort()); + + return { + compress: true, + static: {}, + client: { + logging: 'info', + webSocketURL: { + hostname: local.host, + pathname: local.url, + port: local.port, + }, + }, + host: env.getHost(), + port: env.getPort(), + }; +}; + +/** + * Returns the {@link Configuration} for static type + * @private + */ +// eslint-disable-next-line import/no-unused-modules +export const _getStaticConfiguration = (config: Configuration): Configuration => { + config.static = [getPaths().app.publicDir, getPaths().scripts.devAssetsDir]; + config.historyApiFallback = { + disableDotRule: true, + index: '/', + }; + (config.static as Static).publicPath = '/'; + (config.static as Static).watch = true; + return config; +}; + +/** + * Returns the {@link Configuration} for JS type + * @private + */ +// eslint-disable-next-line import/no-unused-modules +export const _getJavaScriptConfiguration = (config: Configuration): Configuration => { + const socket = env.getWSSocket(); + (config.static as Static).serveIndex = false; + // We're using native sockjs-node + config.webSocketServer = 'ws'; + (config.client as ClientConfiguration).webSocketURL = { + hostname: socket.host, + pathname: socket.path, + port: socket.port, + }; + config.hot = false; + return config; +}; + +/** + * Generates a webpack-dev configuration + */ +/* c8 ignore next */ +export default (type: WebpackTypeWp5): Configuration => { + const config = _getBase(); + + if (type === WebpackTypeWp5.Static) { + return _getStaticConfiguration(config); + } + if (type === WebpackTypeWp5.JavaScript) { + return _getJavaScriptConfiguration(config); + } + + return _getJavaScriptConfiguration(_getStaticConfiguration(config)); +}; diff --git a/packages/flex-plugin-webpack5/tsconfig.json b/packages/flex-plugin-webpack5/tsconfig.json new file mode 100644 index 000000000..46bd62b87 --- /dev/null +++ b/packages/flex-plugin-webpack5/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "compilerOptions": { + "outDir": "dist", + "baseUrl": ".", + "rootDir": "src", + "esModuleInterop": true + } +} diff --git a/packages/flex-plugin-webpack5/tsconfig.lint.json b/packages/flex-plugin-webpack5/tsconfig.lint.json new file mode 100644 index 000000000..b338ddcef --- /dev/null +++ b/packages/flex-plugin-webpack5/tsconfig.lint.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "exclude": [ + "node_modules", + "dist" + ] +} diff --git a/packages/flex-plugin/src/lib/__tests__/flex-plugin.test.ts b/packages/flex-plugin/src/lib/__tests__/flex-plugin.test.ts index 876ef774c..6467feb82 100644 --- a/packages/flex-plugin/src/lib/__tests__/flex-plugin.test.ts +++ b/packages/flex-plugin/src/lib/__tests__/flex-plugin.test.ts @@ -25,8 +25,6 @@ describe('@twilio/flex-plugin', () => { // @ts-ignore global.__FPB_PLUGIN_VERSION = PLUGIN_VERSION; // @ts-ignore - global.__FPB_FLEX_PLUGIN_SCRIPTS_VERSION = FLEX_PLUGIN_SCRIPTS_VERSION; - // @ts-ignore global.__FPB_FLEX_PLUGIN_VERSION = FLEX_PLUGIN_VERSION; // @ts-ignore global.__FPB_FLEX_UI_VERSION = FLEX_UI_VERSION; @@ -67,7 +65,6 @@ describe('@twilio/flex-plugin', () => { expect(plugin.name).toEqual(PLUGIN_NAME); expect(plugin.version).toEqual(PLUGIN_VERSION); expect(plugin.uniqueName).toEqual(UNIQUE_NAME); - expect(plugin.dependencies['@twilio/flex-plugin-scripts']).toEqual(FLEX_PLUGIN_SCRIPTS_VERSION); expect(plugin.dependencies['@twilio/flex-plugin']).toEqual(FLEX_PLUGIN_VERSION); expect(plugin.dependencies['flex-ui']).toEqual(FLEX_UI_VERSION); expect(plugin.dependencies.react).toEqual(REACT_VERSION); diff --git a/packages/flex-plugin/src/lib/flex-plugin.ts b/packages/flex-plugin/src/lib/flex-plugin.ts index 27637bd82..800dc368a 100644 --- a/packages/flex-plugin/src/lib/flex-plugin.ts +++ b/packages/flex-plugin/src/lib/flex-plugin.ts @@ -21,7 +21,6 @@ export abstract class FlexPlugin implements IFlexPlugin { public version: string = __FPB_PLUGIN_VERSION; public dependencies: Record = { - '@twilio/flex-plugin-scripts': __FPB_FLEX_PLUGIN_SCRIPTS_VERSION, '@twilio/flex-plugin': __FPB_FLEX_PLUGIN_VERSION, 'flex-ui': __FPB_FLEX_UI_VERSION, react: __FPB_REACT_VERSION, diff --git a/packages/flex-plugin/src/module.d.ts b/packages/flex-plugin/src/module.d.ts index 925aa3dd3..3de26292b 100644 --- a/packages/flex-plugin/src/module.d.ts +++ b/packages/flex-plugin/src/module.d.ts @@ -12,7 +12,6 @@ declare const Twilio: { declare const __FPB_PLUGIN_UNIQUE_NAME: string; declare const __FPB_PLUGIN_VERSION: string; -declare const __FPB_FLEX_PLUGIN_SCRIPTS_VERSION: string; declare const __FPB_FLEX_PLUGIN_VERSION: string; declare const __FPB_FLEX_UI_VERSION: string; declare const __FPB_REACT_VERSION: string; diff --git a/packages/plugin-flex/package.json b/packages/plugin-flex/package.json index b904ac473..1601651ef 100644 --- a/packages/plugin-flex/package.json +++ b/packages/plugin-flex/package.json @@ -71,7 +71,7 @@ "twilio": "^3.71.2" }, "engines": { - "node": "^16 || ^18 || ^20 || ^22" + "node": "^18 || ^20 || ^22 || ^24" }, "publishConfig": { "access": "public" diff --git a/packages/plugin-flex/src/__tests__/commands/flex/plugins/start.test.ts b/packages/plugin-flex/src/__tests__/commands/flex/plugins/start.test.ts index 9987463a2..96eb07945 100644 --- a/packages/plugin-flex/src/__tests__/commands/flex/plugins/start.test.ts +++ b/packages/plugin-flex/src/__tests__/commands/flex/plugins/start.test.ts @@ -37,7 +37,7 @@ describe('Commands/FlexPluginsStart', () => { const pkg = { name: pluginNameOne, dependencies: { - '@twilio/flex-plugin-scripts': '4.0.0', + '@twilio/flex-plugin': '4.0.0', }, }; const badVersionPkg = { diff --git a/packages/plugin-flex/src/__tests__/commands/flex/plugins/upgrade-plugin.test.ts b/packages/plugin-flex/src/__tests__/commands/flex/plugins/upgrade-plugin.test.ts index 1acb71d55..eaa45e577 100644 --- a/packages/plugin-flex/src/__tests__/commands/flex/plugins/upgrade-plugin.test.ts +++ b/packages/plugin-flex/src/__tests__/commands/flex/plugins/upgrade-plugin.test.ts @@ -66,22 +66,22 @@ describe('Commands/FlexPluginsStart', () => { expect(cmd.getTopicName()).toContain(FlexPluginsUpgradePlugin.topicName); }); - it('should should return then version of @twilio/flex-plugin-scripts from dependencies', async () => { + it('should should return then version of @twilio/flex-plugin from dependencies', async () => { const cmd = await createCommand(); mockGetPkg(cmd, { - dependencies: { '@twilio/flex-plugin-scripts': '3.0.0' }, + dependencies: { '@twilio/flex-plugin': '3.0.0' }, devDependencies: {}, }); expect(cmd.pkgVersion).toEqual(3); }); - it('should should return the version of @twilio/flex-plugin-scripts from devDependencies', async () => { + it('should should return the version of @twilio/flex-plugin from devDependencies', async () => { const cmd = await createCommand(); mockGetPkg(cmd, { dependencies: {}, - devDependencies: { '@twilio/flex-plugin-scripts': '4.0.0' }, + devDependencies: { '@twilio/flex-plugin': '4.0.0' }, }); expect(cmd.pkgVersion).toEqual(4); @@ -738,7 +738,6 @@ describe('Commands/FlexPluginsStart', () => { devDependencies: { '@twilio/flex-ui': '^1', 'react-test-renderer': '16.0.0', - '@twilio/flex-plugin-scripts': '4.1.3', }, dependencies: { react: '15.0.2', @@ -754,7 +753,6 @@ describe('Commands/FlexPluginsStart', () => { 'react-dom': 'react || 16.5.2', }, devDeps: { - '@twilio/flex-plugin-scripts': '*', '@twilio/flex-ui': '^1', 'react-test-renderer': 'react || 16.5.2', }, diff --git a/packages/plugin-flex/src/__tests__/sub-commands/flex-plugin.test.ts b/packages/plugin-flex/src/__tests__/sub-commands/flex-plugin.test.ts index 7de3ca03e..0ecf83d50 100644 --- a/packages/plugin-flex/src/__tests__/sub-commands/flex-plugin.test.ts +++ b/packages/plugin-flex/src/__tests__/sub-commands/flex-plugin.test.ts @@ -246,7 +246,7 @@ describe('SubCommands/FlexPlugin', () => { jest.spyOn(fs, 'readJsonFile').mockReturnValue({ devDependencies: {}, dependencies: { - '@twilio/flex-plugin-scripts': '1.2.3', + '@twilio/flex-plugin': '1.2.3', }, }); @@ -258,7 +258,7 @@ describe('SubCommands/FlexPlugin', () => { jest.spyOn(fs, 'readJsonFile').mockReturnValue({ devDependencies: { - '@twilio/flex-plugin-scripts': '^2.3.4-beta.0', + '@twilio/flex-plugin': '^2.3.4-beta.0', }, dependencies: {}, }); @@ -271,7 +271,7 @@ describe('SubCommands/FlexPlugin', () => { jest.spyOn(fs, 'readJsonFile').mockReturnValue({ devDependencies: { - '@twilio/flex-plugin-scripts': 'not-a-semver', + '@twilio/flex-plugin': 'not-a-semver', }, dependencies: {}, }); diff --git a/packages/plugin-flex/src/commands/flex/plugins/build.ts b/packages/plugin-flex/src/commands/flex/plugins/build.ts index ede5730d6..a9b857fb9 100644 --- a/packages/plugin-flex/src/commands/flex/plugins/build.ts +++ b/packages/plugin-flex/src/commands/flex/plugins/build.ts @@ -1,3 +1,6 @@ +import { flags } from '@oclif/parser'; +import { OutputFlags } from '@oclif/parser/lib/parse'; + import { createDescription } from '../../../utils/general'; import FlexPlugin from '../../../sub-commands/flex-plugin'; @@ -15,14 +18,26 @@ export default class FlexPluginsBuild extends FlexPlugin { static flags = { ...baseFlags, + wp5: flags.boolean({ + description: FlexPluginsBuild.topic.flags.wp5, + default: false, + }), }; + // @ts-ignore + public _flags: OutputFlags; + + async init(): Promise { + this._flags = (await this.parseCommand(FlexPluginsBuild)).flags; + } + /** * @override */ async doRun(): Promise { process.env.PERSIST_TERMINAL = 'true'; await this.runScript('pre-script-check'); + this.scriptArgs = this._flags.wp5 ? ['--wp5'] : []; await this.runScript('build'); } diff --git a/packages/plugin-flex/src/commands/flex/plugins/start.ts b/packages/plugin-flex/src/commands/flex/plugins/start.ts index 39c313c41..05d95545c 100644 --- a/packages/plugin-flex/src/commands/flex/plugins/start.ts +++ b/packages/plugin-flex/src/commands/flex/plugins/start.ts @@ -39,6 +39,10 @@ export default class FlexPluginsStart extends FlexPlugin { 'flex-ui-source': flags.string({ hidden: true, }), + wp5: flags.boolean({ + description: FlexPluginsStart.topic.flags.wp5, + default: false, + }), }; // @ts-ignore @@ -92,9 +96,7 @@ export default class FlexPluginsStart extends FlexPlugin { } } - if (this._flags['include-remote']) { - flexArgs.push('--include-remote'); - } + this.appendBooleanFlags(flexArgs); if (this._flags['flex-ui-source']) { env.setFlexUISrc(this._flags['flex-ui-source']); @@ -134,14 +136,18 @@ export default class FlexPluginsStart extends FlexPlugin { await this.runScript('start', ['flex', ...flexArgs, '--plugin-config', JSON.stringify(pluginsConfig)]); for (let i = 0; localPluginNames && i < localPluginNames.length; i++) { - // eslint-disable-next-line @typescript-eslint/no-floating-promises - this.spawnScript('start', [ + const pluginArgs = [ 'plugin', '--name', localPluginNames[i], '--port', pluginsConfig[localPluginNames[i]].port.toString(), - ]); + ]; + if (this._flags.wp5) { + pluginArgs.push('--wp5'); + } + // eslint-disable-next-line @typescript-eslint/no-floating-promises + this.spawnScript('start', pluginArgs); } } } @@ -167,9 +173,9 @@ export default class FlexPluginsStart extends FlexPlugin { // Verify plugin's flex-plugin-scripts is v4 const pkgDir = `${plugin.dir}/package.json`; const pkg = readJsonFile(pkgDir); - let scriptVersion = semver.coerce(pkg.dependencies['@twilio/flex-plugin-scripts']); + let scriptVersion = semver.coerce(pkg.dependencies['@twilio/flex-plugin']); if (!scriptVersion) { - scriptVersion = semver.coerce(pkg.devDependencies['@twilio/flex-plugin-scripts']); + scriptVersion = semver.coerce(pkg.devDependencies['@twilio/flex-plugin']); } } @@ -253,4 +259,18 @@ export default class FlexPluginsStart extends FlexPlugin { return false; } + + /** + * Appends the simple boolean pass-through flags to the flex-plugin-scripts args + * @param flexArgs the args array to append to + * @private + */ + private appendBooleanFlags(flexArgs: string[]): void { + if (this._flags['include-remote']) { + flexArgs.push('--include-remote'); + } + if (this._flags.wp5) { + flexArgs.push('--wp5'); + } + } } diff --git a/packages/plugin-flex/src/commands/flex/plugins/upgrade-plugin.ts b/packages/plugin-flex/src/commands/flex/plugins/upgrade-plugin.ts index 7fa741151..34022754b 100644 --- a/packages/plugin-flex/src/commands/flex/plugins/upgrade-plugin.ts +++ b/packages/plugin-flex/src/commands/flex/plugins/upgrade-plugin.ts @@ -24,7 +24,6 @@ const appConfig = 'appConfig.js'; const crackoConfig = 'craco.config.js'; const flexUI = '@twilio/flex-ui'; -const scopedFlexPluginScriptPackage = '@twilio/flex-plugin-scripts'; const flexPluginScriptPackage = 'flex-plugin-scripts'; const scopedFlexPluginPackage = '@twilio/flex-plugin'; const flexPluginPackage = 'flex-plugin'; @@ -83,7 +82,6 @@ export default class FlexPluginsUpgradePlugin extends FlexPlugin { }; static packagesToRemove = [ - scopedFlexPluginScriptPackage, // remove and then re-add 'react-app-rewire-flex-plugin', 'react-app-rewired', 'react-scripts', @@ -186,10 +184,7 @@ export default class FlexPluginsUpgradePlugin extends FlexPlugin { return; } - const pkgJson = await packages.getRegistryVersion( - scopedFlexPluginScriptPackage, - this._flags.beta ? 'beta' : 'latest', - ); + const pkgJson = await packages.getRegistryVersion(scopedFlexPluginPackage, this._flags.beta ? 'beta' : 'latest'); const latestVersion = pkgJson ? semver.coerce(pkgJson.version as string)?.major : 0; if (currentPkgVersion !== latestVersion) { await this.cleanupNodeModules(); @@ -537,7 +532,6 @@ export default class FlexPluginsUpgradePlugin extends FlexPlugin { [scopedFlexPluginPackage]: '*', }, devDeps: { - [scopedFlexPluginScriptPackage]: '*', [flexUI]: '^1', 'react-test-renderer': react, }, @@ -584,16 +578,12 @@ export default class FlexPluginsUpgradePlugin extends FlexPlugin { */ get pkgVersion(): number | undefined { const pkg = - this.pkg.dependencies[scopedFlexPluginScriptPackage] || - this.pkg.devDependencies[scopedFlexPluginScriptPackage] || - this.pkg.dependencies[flexPluginScriptPackage] || - this.pkg.devDependencies[flexPluginScriptPackage] || this.pkg.dependencies[scopedFlexPluginPackage] || this.pkg.devDependencies[scopedFlexPluginPackage] || this.pkg.dependencies[flexPluginPackage] || this.pkg.devDependencies[flexPluginPackage]; if (!pkg) { - throw new TwilioCliError(`Package '${scopedFlexPluginScriptPackage}' was not found`); + throw new TwilioCliError(`Package '${scopedFlexPluginPackage}' was not found`); } return semver.coerce(pkg)?.major; diff --git a/packages/plugin-flex/src/sub-commands/flex-plugin.ts b/packages/plugin-flex/src/sub-commands/flex-plugin.ts index 17b1844e7..2c5141601 100644 --- a/packages/plugin-flex/src/sub-commands/flex-plugin.ts +++ b/packages/plugin-flex/src/sub-commands/flex-plugin.ts @@ -54,6 +54,7 @@ interface FlexPluginOption { runTelemetryAsync: boolean; } +const flexPlugin = '@twilio/flex-plugin'; const flexPluginScripts = '@twilio/flex-plugin-scripts'; export type ConfigData = typeof services.config.ConfigData; @@ -295,11 +296,7 @@ export default class FlexPlugin extends baseCommands.TwilioClientCommand { */ get builderVersion(): number | null { const { pkg } = this; - const script = - pkg.dependencies[flexPluginScripts] || - pkg.devDependencies[flexPluginScripts] || - pkg.dependencies['flex-plugin-scripts'] || - pkg.devDependencies['flex-plugin-scripts']; + const script = pkg.dependencies[flexPlugin] || pkg.devDependencies[flexPlugin]; if (!script) { return null; } @@ -450,8 +447,8 @@ export default class FlexPlugin extends baseCommands.TwilioClientCommand { } if (this.opts.runInDirectory) { - const pluginScriptVersion = FlexPlugin.getPackageVersion(join(this.cwd, 'node_modules', flexPluginScripts)); - this.logger.debug(`Using ${flexPluginScripts} version ${pluginScriptVersion}`); + const pluginScriptVersion = FlexPlugin.getPackageVersion(join(this.cwd, 'node_modules', flexPlugin)); + this.logger.debug(`Using ${flexPlugin} version ${pluginScriptVersion}`); if (!this.isPluginFolder()) { throw new TwilioCliError(this.pluginFolderErrorMessage);