From 1aaac78311eef9e28e69869dc1d2e2dbfbdf6f7f Mon Sep 17 00:00:00 2001 From: Bob Hemphill Date: Fri, 26 Sep 2025 10:28:20 -0600 Subject: [PATCH 01/10] fix: publish next [EXT-6803] From a8acbf0d40ac855e2c2f0049d4ed291b67364d4c Mon Sep 17 00:00:00 2001 From: "contentful-automation[bot]" <100587065+contentful-automation[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 16:56:20 +0000 Subject: [PATCH 02/10] chore(release): 3.13.2-next.1 [skip ci] ## [3.13.2-next.1](https://github.com/contentful/node-apps-toolkit/compare/v3.13.1...v3.13.2-next.1) (2025-09-26) ### Bug Fixes * publish next [EXT-6803] ([1aaac78](https://github.com/contentful/node-apps-toolkit/commit/1aaac78311eef9e28e69869dc1d2e2dbfbdf6f7f)) --- CHANGELOG.md | 7 +++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c8d3c02c..99637c15 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [3.13.2-next.1](https://github.com/contentful/node-apps-toolkit/compare/v3.13.1...v3.13.2-next.1) (2025-09-26) + + +### Bug Fixes + +* publish next [EXT-6803] ([1aaac78](https://github.com/contentful/node-apps-toolkit/commit/1aaac78311eef9e28e69869dc1d2e2dbfbdf6f7f)) + ## [3.13.1](https://github.com/contentful/node-apps-toolkit/compare/v3.13.0...v3.13.1) (2025-05-28) diff --git a/package-lock.json b/package-lock.json index f54c1720..45b7f354 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@contentful/node-apps-toolkit", - "version": "3.13.1", + "version": "3.13.2-next.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@contentful/node-apps-toolkit", - "version": "3.13.1", + "version": "3.13.2-next.1", "license": "MIT", "dependencies": { "@types/debug": "^4.1.5", diff --git a/package.json b/package.json index 7b86fdb3..623411a6 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentful/node-apps-toolkit", - "version": "3.13.1", + "version": "3.13.2-next.1", "description": "A collection of helpers and utilities for creating NodeJS Contentful Apps", "main": "lib/index.cjs", "module": "lib/index.mjs", From 2f42033604a0ce8f7e702eaf100c4d31fa426ef6 Mon Sep 17 00:00:00 2001 From: Bob Hemphill Date: Fri, 26 Sep 2025 11:31:54 -0600 Subject: [PATCH 03/10] feat: swap got for ky --- package-lock.json | 273 +++----------------------- package.json | 2 +- src/keys/get-management-token.spec.ts | 23 ++- src/keys/get-management-token.ts | 24 +-- src/utils/http.ts | 34 ++-- src/utils/index.ts | 2 +- test/utils.ts | 10 +- 7 files changed, 83 insertions(+), 285 deletions(-) diff --git a/package-lock.json b/package-lock.json index 45b7f354..70bf6d69 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,8 +12,8 @@ "@types/debug": "^4.1.5", "contentful-management": "^11.6.1", "debug": "^4.2.0", - "got": "^11.7.0", "jsonwebtoken": "^9.0.0", + "ky": "^1.10.0", "lru-cache": "^10.4.3", "runtypes": "^5.0.1" }, @@ -1911,6 +1911,7 @@ "version": "4.6.0", "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", + "dev": true, "engines": { "node": ">=10" }, @@ -1974,17 +1975,6 @@ "integrity": "sha512-sXXKG+uL9IrKqViTtao2Ws6dy0znu9sOaP1di/jKGW1M6VssO8vlpXCQcpZ+jisQ1tTFAC5Jo/EOzFbggBagFQ==", "dev": true }, - "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" - } - }, "node_modules/@tsconfig/node10": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz", @@ -2009,17 +1999,6 @@ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } - }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -2035,11 +2014,6 @@ "dev": true, "license": "MIT" }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==" - }, "node_modules/@types/jsonwebtoken": { "version": "9.0.6", "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz", @@ -2049,14 +2023,6 @@ "@types/node": "*" } }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/mocha": { "version": "10.0.6", "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", @@ -2072,6 +2038,7 @@ "version": "22.5.4", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", + "dev": true, "dependencies": { "undici-types": "~6.19.2" } @@ -2082,14 +2049,6 @@ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true }, - "node_modules/@types/responselike": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", - "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", - "dependencies": { - "@types/node": "*" - } - }, "node_modules/@types/sinon": { "version": "17.0.3", "resolved": "https://registry.npmjs.org/@types/sinon/-/sinon-17.0.3.tgz", @@ -2848,45 +2807,6 @@ "node": ">=8" } }, - "node_modules/cacheable-lookup": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-5.0.4.tgz", - "integrity": "sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==", - "engines": { - "node": ">=10.6.0" - } - }, - "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" - } - }, - "node_modules/cacheable-request/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" - } - }, "node_modules/call-bind": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", @@ -3226,17 +3146,6 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", - "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -3654,31 +3563,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "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" - } - }, - "node_modules/decompress-response/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" - } - }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", @@ -3694,14 +3578,6 @@ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", "dev": true }, - "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" - } - }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -3851,14 +3727,6 @@ "integrity": "sha512-5U0rVMU5Y2n2+ykNLQqMoqklN9ICBT/KsvC1Gz6vqHbz2AXXGkG+Pm5rMWk/8Vjrr/mY9985Hi8DYzn1F09Nyw==", "dev": true }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dependencies": { - "once": "^1.4.0" - } - }, "node_modules/env-ci": { "version": "11.0.0", "resolved": "https://registry.npmjs.org/env-ci/-/env-ci-11.0.0.tgz", @@ -5038,30 +4906,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "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" - } - }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", @@ -5216,11 +5060,6 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==" - }, "node_modules/http-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", @@ -5234,18 +5073,6 @@ "node": ">= 14" } }, - "node_modules/http2-wrapper": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-1.0.3.tgz", - "integrity": "sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==", - "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.0.0" - }, - "engines": { - "node": ">=10.19.0" - } - }, "node_modules/https-proxy-agent": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.4.tgz", @@ -5873,7 +5700,8 @@ "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==" + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true }, "node_modules/json-parse-better-errors": { "version": "1.0.2", @@ -5998,10 +5826,23 @@ "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, "dependencies": { "json-buffer": "3.0.1" } }, + "node_modules/ky": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/ky/-/ky-1.10.0.tgz", + "integrity": "sha512-YRPCzHEWZffbfvmRrfwa+5nwBHwZuYiTrfDX0wuhGBPV0pA/zCqcOq93MDssON/baIkpYbvehIX5aLpMxrRhaA==", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sindresorhus/ky?sponsor=1" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -6502,14 +6343,6 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "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" - } - }, "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", @@ -6676,14 +6509,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/mimic-response": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-1.0.1.tgz", - "integrity": "sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==", - "engines": { - "node": ">=4" - } - }, "node_modules/minimatch": { "version": "9.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", @@ -6887,17 +6712,6 @@ "node": ">=0.10.0" } }, - "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" - } - }, "node_modules/npm": { "version": "10.8.0", "resolved": "https://registry.npmjs.org/npm/-/npm-10.8.0.tgz", @@ -9578,6 +9392,7 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dev": true, "dependencies": { "wrappy": "1" } @@ -9614,14 +9429,6 @@ "node": ">= 0.8.0" } }, - "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" - } - }, "node_modules/p-each-series": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-3.0.0.tgz", @@ -10116,15 +9923,6 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, - "node_modules/pump": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", - "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dependencies": { - "end-of-stream": "^1.1.0", - "once": "^1.3.1" - } - }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", @@ -10170,17 +9968,6 @@ } ] }, - "node_modules/quick-lru": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", - "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", @@ -10387,11 +10174,6 @@ "node": ">=0.10.0" } }, - "node_modules/resolve-alpn": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/resolve-alpn/-/resolve-alpn-1.2.1.tgz", - "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==" - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -10401,17 +10183,6 @@ "node": ">=4" } }, - "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" - } - }, "node_modules/restore-cursor": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", @@ -12508,7 +12279,8 @@ "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==" + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", + "dev": true }, "node_modules/unicode-emoji-modifier-base": { "version": "1.0.0", @@ -12907,7 +12679,8 @@ "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", + "dev": true }, "node_modules/xtend": { "version": "4.0.2", diff --git a/package.json b/package.json index 623411a6..eb265fce 100644 --- a/package.json +++ b/package.json @@ -55,8 +55,8 @@ "@types/debug": "^4.1.5", "contentful-management": "^11.6.1", "debug": "^4.2.0", - "got": "^11.7.0", "jsonwebtoken": "^9.0.0", + "ky": "^1.10.0", "lru-cache": "^10.4.3", "runtypes": "^5.0.1" }, diff --git a/src/keys/get-management-token.spec.ts b/src/keys/get-management-token.spec.ts index d0fd9b6d..33e41c27 100644 --- a/src/keys/get-management-token.spec.ts +++ b/src/keys/get-management-token.spec.ts @@ -9,7 +9,7 @@ import { getManagementToken, GetManagementTokenOptions, } from './get-management-token' -import { HttpClient, HttpError, Response } from '../utils' +import { HttpClient, HttpError, Response, Request, ErrorOptions } from '../utils' import { Logger } from '../utils' import { sign } from 'jsonwebtoken' import { LRUCache } from 'lru-cache' @@ -33,7 +33,9 @@ describe('getManagementToken', () => { const mockToken = 'token' const logger = noop as unknown as Logger const post = sinon.stub() - post.resolves({ statusCode: 201, body: JSON.stringify({ token: mockToken }) }) + post.returns({ + json: () => Promise.resolve({ token: mockToken }), + }) const httpClient = { post } as unknown as HttpClient const getManagementToken = createGetManagementToken(logger, httpClient, defaultCache) @@ -55,7 +57,7 @@ describe('getManagementToken', () => { expiresIn: '10 minutes', }) - post.resolves({ statusCode: 201, body: JSON.stringify({ token: mockToken }) }) + post.returns({ json: () => Promise.resolve({ token: mockToken }) }) const httpClient = { post } as unknown as HttpClient const getManagementToken = createGetManagementToken(logger, httpClient, defaultCache) @@ -75,7 +77,7 @@ describe('getManagementToken', () => { expiresIn: '5 minutes', }) - post.resolves({ statusCode: 201, body: JSON.stringify({ token: mockToken }) }) + post.returns({ json: () => Promise.resolve({ token: mockToken }) }) const httpClient = { post } as unknown as HttpClient const cache: LRUCache = new LRUCache({ max: 10 }) const getManagementToken = createGetManagementToken(logger, httpClient, cache) @@ -103,7 +105,7 @@ describe('getManagementToken', () => { const mockToken = 'token' const logger = noop as unknown as Logger const post = sinon.stub() - post.resolves({ statusCode: 201, body: JSON.stringify({ token: mockToken }) }) + post.returns({ json: () => Promise.resolve({ token: mockToken }) }) const httpClient = { post } as unknown as HttpClient const getManagementToken = createGetManagementToken(logger, httpClient, defaultCache) @@ -136,7 +138,16 @@ describe('getManagementToken', () => { describe('when having API problems', () => { it(`throws when API returns an error`, async () => { const logger = noop as unknown as Logger - const post = sinon.stub().rejects(new HttpError({ statusCode: 500 } as unknown as Response)) + const post = sinon.stub().returns({ + json: () => + Promise.reject( + new HttpError( + { statusCode: 500 } as unknown as Response, + {} as unknown as Request, + {} as unknown as ErrorOptions, + ), + ), + }) const httpClient = { post } as unknown as HttpClient const getManagementToken = createGetManagementToken(logger, httpClient, defaultCache) diff --git a/src/keys/get-management-token.ts b/src/keys/get-management-token.ts index 1d62e876..7c314d60 100644 --- a/src/keys/get-management-token.ts +++ b/src/keys/get-management-token.ts @@ -58,23 +58,25 @@ const getTokenFromOneTimeToken = async ( log(`Requesting CMA Token with given App Token`) - const response = await http.post( - `spaces/${spaceId}/environments/${environmentId}/app_installations/${appInstallationId}/access_tokens`, - { - headers: { - Authorization: `Bearer ${appToken}`, + const response = await http + .post( + `spaces/${spaceId}/environments/${environmentId}/app_installations/${appInstallationId}/access_tokens`, + { + headers: { + Authorization: `Bearer ${appToken}`, + }, + hooks: { + afterResponse: [validateStatusCode], + }, }, - hooks: { - afterResponse: [validateStatusCode], - }, - }, - ) + ) + .json<{ token: string }>() log( `Successfully retrieved CMA Token for app ${appInstallationId} in space ${spaceId} and environment ${environmentId}`, ) - return JSON.parse(response.body).token + return response.token } /** diff --git a/src/utils/http.ts b/src/utils/http.ts index 84450844..f87e8916 100644 --- a/src/utils/http.ts +++ b/src/utils/http.ts @@ -1,23 +1,35 @@ -import got, { ExtendOptions, Got, HTTPError, Response as GotResponse } from 'got' +import ky, { + Options, + KyInstance, + HTTPError, + KyResponse, + AfterResponseHook, + KyRequest, + NormalizedOptions, +} from 'ky' const config = { prefixUrl: process.env.BASE_URL || 'https://api.contentful.com', retry: { limit: 3 }, } -export const createHttpClient = (configOverride: ExtendOptions = {}) => { - return got.extend({ ...config, ...configOverride }) +export const createHttpClient = (configOverride: Options = {}) => { + return ky.extend({ ...config, ...configOverride }) } -export const createValidateStatusCode = (allowedStatusCodes: number[]) => (response: Response) => { - if (!allowedStatusCodes.includes(response.statusCode)) { - console.log(response.body) - throw new HTTPError(response) +export const createValidateStatusCode = + (allowedStatusCodes: number[]): AfterResponseHook => + (request: KyRequest, options: NormalizedOptions, response: KyResponse) => { + if (!allowedStatusCodes.includes(response.status)) { + console.log(response.body) + throw new HTTPError(response, request, options) + } + return response } - return response -} export { HTTPError as HttpError } -export type HttpClient = Got -export type Response = GotResponse +export type HttpClient = KyInstance +export type Request = KyRequest +export type Response = KyResponse +export type ErrorOptions = NormalizedOptions diff --git a/src/utils/index.ts b/src/utils/index.ts index 90726d6f..a759a8b8 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,4 +1,4 @@ -export type { Response, HttpClient } from './http' +export type { Response, HttpClient, Request, ErrorOptions } from './http' export { createHttpClient, createValidateStatusCode, HttpError } from './http' export { createLogger } from './logger' export type { Logger } from './logger' diff --git a/test/utils.ts b/test/utils.ts index 3962ea92..7a54e633 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -14,14 +14,14 @@ export const cleanOldKeys = async () => { const organizationId = process.env.ORGANIZATION_ID const appDefinitionId = process.env.APP_ID - const { body } = await http.get( - `organizations/${organizationId}/app_definitions/${appDefinitionId}/keys` - ) - const fingerprints = JSON.parse(body).items.map((i: any) => i.jwk.x5t) + const { items } = await http + .get(`organizations/${organizationId}/app_definitions/${appDefinitionId}/keys`) + .json<{ items: { jwk: { x5t: string } }[] }>() + const fingerprints = items.map((i: any) => i.jwk.x5t) const deleteKeysRequests = fingerprints.map((fingerprint: string) => { return http.delete( - `organizations/${organizationId}/app_definitions/${appDefinitionId}/keys/${fingerprint}` + `organizations/${organizationId}/app_definitions/${appDefinitionId}/keys/${fingerprint}`, ) }) From 4f248134660de9c32d7a61f481068dc3a2c5144e Mon Sep 17 00:00:00 2001 From: Bob Hemphill Date: Fri, 26 Sep 2025 11:54:09 -0600 Subject: [PATCH 04/10] fix: cjs compat --- src/keys/get-management-token.ts | 4 ++-- src/utils/http.ts | 5 +++-- test/integration/keys.test.ts | 4 ++-- test/utils.ts | 13 ++++++++----- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/keys/get-management-token.ts b/src/keys/get-management-token.ts index 7c314d60..daa33097 100644 --- a/src/keys/get-management-token.ts +++ b/src/keys/get-management-token.ts @@ -149,7 +149,7 @@ export const createGetManagementToken = ( * ~~~ * @category Keys */ -export const getManagementToken = (privateKey: string, opts: GetManagementTokenOptions) => { +export const getManagementToken = async (privateKey: string, opts: GetManagementTokenOptions) => { if ((opts.reuseToken || opts.reuseToken === undefined) && !defaultCache) { defaultCache = new LRUCache({ max: 10 }) } @@ -157,7 +157,7 @@ export const getManagementToken = (privateKey: string, opts: GetManagementTokenO return createGetManagementToken( createLogger({ filename: __filename }), - createHttpClient(httpClientOpts), + await createHttpClient(httpClientOpts), defaultCache!, )(privateKey, opts) } diff --git a/src/utils/http.ts b/src/utils/http.ts index f87e8916..70727382 100644 --- a/src/utils/http.ts +++ b/src/utils/http.ts @@ -1,4 +1,4 @@ -import ky, { +import { Options, KyInstance, HTTPError, @@ -13,7 +13,8 @@ const config = { retry: { limit: 3 }, } -export const createHttpClient = (configOverride: Options = {}) => { +export const createHttpClient = async (configOverride: Options = {}) => { + const { default: ky } = await import('ky') return ky.extend({ ...config, ...configOverride }) } diff --git a/test/integration/keys.test.ts b/test/integration/keys.test.ts index ba658b81..5901bbdf 100644 --- a/test/integration/keys.test.ts +++ b/test/integration/keys.test.ts @@ -32,8 +32,8 @@ describe('Keys Utilities', () => { environmentId, }) - await assert.doesNotReject(() => { - const http = createHttpClient() + await assert.doesNotReject(async () => { + const http = await createHttpClient() return http.get(`spaces/${spaceId}/entries`, { headers: { diff --git a/test/utils.ts b/test/utils.ts index 7a54e633..84756115 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -4,16 +4,18 @@ import base64url from 'base64url' import { createHttpClient, createValidateStatusCode } from '../src/utils' -const http = createHttpClient({ - headers: { - Authorization: `Bearer ${process.env.PERSONAL_ACCESS_TOKEN}`, - }, -}) +const httpFactory = async () => + await createHttpClient({ + headers: { + Authorization: `Bearer ${process.env.PERSONAL_ACCESS_TOKEN}`, + }, + }) export const cleanOldKeys = async () => { const organizationId = process.env.ORGANIZATION_ID const appDefinitionId = process.env.APP_ID + const http = await httpFactory() const { items } = await http .get(`organizations/${organizationId}/app_definitions/${appDefinitionId}/keys`) .json<{ items: { jwk: { x5t: string } }[] }>() @@ -33,6 +35,7 @@ export const setPublicKey = async (publicKey: Buffer) => { const appDefinitionId = process.env.APP_ID const keyId = base64url(crypto.createHash('sha256').update(publicKey).digest()) + const http = await httpFactory() return http.post(`organizations/${organizationId}/app_definitions/${appDefinitionId}/keys`, { json: { jwk: { From 8ede9d19480e9cb943d9fe336ed3f4f213580e80 Mon Sep 17 00:00:00 2001 From: Bob Hemphill Date: Fri, 26 Sep 2025 16:49:08 -0600 Subject: [PATCH 05/10] fix: cloudflare compliant [EXT-6803] --- .eslintrc.js | 3 + .gitignore | 4 +- package-lock.json | 24 +++---- package.json | 2 +- src/keys/get-management-token.spec.ts | 93 ++++++++++++++++----------- src/keys/get-management-token.ts | 43 ++++++------- src/utils/http.ts | 81 +++++++++++++++-------- src/utils/index.ts | 3 +- test/integration/keys.test.ts | 21 +++--- test/utils.ts | 72 +++++++++++++-------- tsconfig.eslint.json | 8 +++ 11 files changed, 212 insertions(+), 142 deletions(-) create mode 100644 tsconfig.eslint.json diff --git a/.eslintrc.js b/.eslintrc.js index 716e35c8..bd8ac53e 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -4,6 +4,9 @@ module.exports = { node: true, mocha: true, }, + parserOptions: { + project: './tsconfig.eslint.json', + }, plugins: ['@typescript-eslint', 'prettier'], extends: ['eslint:recommended', 'plugin:prettier/recommended'], rules: { diff --git a/.gitignore b/.gitignore index c589982b..43b7ea58 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ node_modules keys .env docs -lib \ No newline at end of file +lib + +envs \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 70bf6d69..9d180d87 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,7 +22,7 @@ "@semantic-release/git": "10.0.1", "@types/jsonwebtoken": "9.0.6", "@types/mocha": "10.0.6", - "@types/node": "22.5.4", + "@types/node": "^22.18.6", "@types/sinon": "17.0.3", "@typescript-eslint/eslint-plugin": "7.10.0", "@typescript-eslint/parser": "7.10.0", @@ -2035,14 +2035,20 @@ "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==" }, "node_modules/@types/node": { - "version": "22.5.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.4.tgz", - "integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==", - "dev": true, + "version": "22.18.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.6.tgz", + "integrity": "sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ==", + "license": "MIT", "dependencies": { - "undici-types": "~6.19.2" + "undici-types": "~6.21.0" } }, + "node_modules/@types/node/node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "license": "MIT" + }, "node_modules/@types/normalize-package-data": { "version": "2.4.4", "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", @@ -12276,12 +12282,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/undici-types": { - "version": "6.19.8", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", - "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", - "dev": true - }, "node_modules/unicode-emoji-modifier-base": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unicode-emoji-modifier-base/-/unicode-emoji-modifier-base-1.0.0.tgz", diff --git a/package.json b/package.json index eb265fce..30921ec0 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "@semantic-release/git": "10.0.1", "@types/jsonwebtoken": "9.0.6", "@types/mocha": "10.0.6", - "@types/node": "22.5.4", + "@types/node": "^22.18.6", "@types/sinon": "17.0.3", "@typescript-eslint/eslint-plugin": "7.10.0", "@typescript-eslint/parser": "7.10.0", diff --git a/src/keys/get-management-token.spec.ts b/src/keys/get-management-token.spec.ts index 33e41c27..cab1eded 100644 --- a/src/keys/get-management-token.spec.ts +++ b/src/keys/get-management-token.spec.ts @@ -9,7 +9,7 @@ import { getManagementToken, GetManagementTokenOptions, } from './get-management-token' -import { HttpClient, HttpError, Response, Request, ErrorOptions } from '../utils' +import { HttpError } from '../utils' import { Logger } from '../utils' import { sign } from 'jsonwebtoken' import { LRUCache } from 'lru-cache' @@ -27,39 +27,52 @@ const DEFAULT_OPTIONS: GetManagementTokenOptions = { const noop = () => {} const defaultCache: LRUCache = new LRUCache({ max: 10 }) +let fetchStub: sinon.SinonStub + +beforeEach(() => { + fetchStub = sinon.stub(global, 'fetch') +}) + +afterEach(() => { + fetchStub.restore() +}) describe('getManagementToken', () => { it('fetches a token', async () => { const mockToken = 'token' const logger = noop as unknown as Logger - const post = sinon.stub() - post.returns({ - json: () => Promise.resolve({ token: mockToken }), - }) - const httpClient = { post } as unknown as HttpClient - const getManagementToken = createGetManagementToken(logger, httpClient, defaultCache) + fetchStub.resolves({ ok: true, status: 201, json: () => Promise.resolve({ token: mockToken }) }) + const getManagementToken = createGetManagementToken( + logger, + { prefixUrl: '', retry: { limit: 0 } }, + defaultCache, + ) const result = await getManagementToken(PRIVATE_KEY, DEFAULT_OPTIONS) assert.deepStrictEqual(result, mockToken) + assert(fetchStub.calledOnce) + console.log(fetchStub.args) assert( - post.calledWith( - `spaces/${SPACE_ID}/environments/${ENVIRONMENT_ID}/app_installations/${APP_ID}/access_tokens`, - sinon.match({ headers: { Authorization: sinon.match.string } }), + fetchStub.calledWith( + `/spaces/${SPACE_ID}/environments/${ENVIRONMENT_ID}/app_installations/${APP_ID}/access_tokens`, + sinon.match({ method: 'POST', headers: { Authorization: sinon.match.string } }), ), ) }) it('caches token while valid', async () => { const logger = noop as unknown as Logger - const post = sinon.stub() const mockToken = sign({ a: 'b' }, 'a-secret-key', { expiresIn: '10 minutes', }) - post.returns({ json: () => Promise.resolve({ token: mockToken }) }) - const httpClient = { post } as unknown as HttpClient - const getManagementToken = createGetManagementToken(logger, httpClient, defaultCache) + fetchStub.resolves({ ok: true, status: 201, json: () => Promise.resolve({ token: mockToken }) }) + const getManagementToken = createGetManagementToken( + logger, + { prefixUrl: '', retry: { limit: 0 } }, + defaultCache, + ) const optionsWithCaching = { ...DEFAULT_OPTIONS, reuseToken: true } const result = await getManagementToken(PRIVATE_KEY, optionsWithCaching) @@ -67,20 +80,22 @@ describe('getManagementToken', () => { const secondResult = await getManagementToken(PRIVATE_KEY, optionsWithCaching) assert.strictEqual(secondResult, mockToken) - assert(post.calledOnce) + assert(fetchStub.calledOnce) }) it('does not cache expired token', async () => { const logger = noop as unknown as Logger - const post = sinon.stub() const mockToken = sign({ a: 'b' }, 'a-secret-key', { expiresIn: '5 minutes', }) - post.returns({ json: () => Promise.resolve({ token: mockToken }) }) - const httpClient = { post } as unknown as HttpClient + fetchStub.resolves({ ok: true, status: 201, json: () => Promise.resolve({ token: mockToken }) }) const cache: LRUCache = new LRUCache({ max: 10 }) - const getManagementToken = createGetManagementToken(logger, httpClient, cache) + const getManagementToken = createGetManagementToken( + logger, + { prefixUrl: '', retry: { limit: 0 } }, + cache, + ) const optionsWithCaching = { ...DEFAULT_OPTIONS, reuseToken: true } const result = await getManagementToken(PRIVATE_KEY, optionsWithCaching) @@ -97,25 +112,31 @@ describe('getManagementToken', () => { const secondResult = await getManagementToken(PRIVATE_KEY, optionsWithCaching) assert.strictEqual(secondResult, mockToken) - assert(post.calledTwice) + assert(fetchStub.calledTwice) }) describe('when using a keyId', () => { it('fetches a token', async () => { const mockToken = 'token' const logger = noop as unknown as Logger - const post = sinon.stub() - post.returns({ json: () => Promise.resolve({ token: mockToken }) }) - const httpClient = { post } as unknown as HttpClient - const getManagementToken = createGetManagementToken(logger, httpClient, defaultCache) + fetchStub.resolves({ + ok: true, + status: 201, + json: () => Promise.resolve({ token: mockToken }), + }) + const getManagementToken = createGetManagementToken( + logger, + { prefixUrl: '', retry: { limit: 0 } }, + defaultCache, + ) const result = await getManagementToken(PRIVATE_KEY, { ...DEFAULT_OPTIONS, keyId: 'keyId' }) assert.deepStrictEqual(result, mockToken) assert( - post.calledWith( - `spaces/${SPACE_ID}/environments/${ENVIRONMENT_ID}/app_installations/${APP_ID}/access_tokens`, - sinon.match({ headers: { Authorization: sinon.match.string } }), + fetchStub.calledWith( + `/spaces/${SPACE_ID}/environments/${ENVIRONMENT_ID}/app_installations/${APP_ID}/access_tokens`, + sinon.match({ method: 'POST', headers: { Authorization: sinon.match.string } }), ), ) }) @@ -138,18 +159,12 @@ describe('getManagementToken', () => { describe('when having API problems', () => { it(`throws when API returns an error`, async () => { const logger = noop as unknown as Logger - const post = sinon.stub().returns({ - json: () => - Promise.reject( - new HttpError( - { statusCode: 500 } as unknown as Response, - {} as unknown as Request, - {} as unknown as ErrorOptions, - ), - ), - }) - const httpClient = { post } as unknown as HttpClient - const getManagementToken = createGetManagementToken(logger, httpClient, defaultCache) + fetchStub.rejects(new HttpError({ statusCode: 500 } as unknown as Response)) + const getManagementToken = createGetManagementToken( + logger, + { prefixUrl: '', retry: { limit: 0 } }, + defaultCache, + ) await assert.rejects(async () => { await getManagementToken(PRIVATE_KEY, DEFAULT_OPTIONS) diff --git a/src/keys/get-management-token.ts b/src/keys/get-management-token.ts index daa33097..bf7f7d27 100644 --- a/src/keys/get-management-token.ts +++ b/src/keys/get-management-token.ts @@ -1,13 +1,8 @@ import * as jwtImpl from 'jsonwebtoken' import type { SignOptions } from 'jsonwebtoken' import { LRUCache } from 'lru-cache' -import { - createLogger, - Logger, - createHttpClient, - createValidateStatusCode, - HttpClient, -} from '../utils' +import { createLogger, Logger, createValidateStatusCode } from '../utils' +import { FetchOptions, makeRequest, withDefaultOptions, withHook, withRetry } from '../utils/http' const jwt = 'default' in jwtImpl ? jwtImpl.default : jwtImpl const { sign, decode } = jwt as typeof jwtImpl @@ -52,31 +47,31 @@ const getTokenFromOneTimeToken = async ( spaceId, environmentId, }: { appInstallationId: string; spaceId: string; environmentId: string }, - { log, http }: { log: Logger; http: HttpClient }, + { log, fetchOptions }: { log: Logger; fetchOptions: FetchOptions }, ): Promise => { const validateStatusCode = createValidateStatusCode([201]) log(`Requesting CMA Token with given App Token`) - const response = await http - .post( - `spaces/${spaceId}/environments/${environmentId}/app_installations/${appInstallationId}/access_tokens`, - { - headers: { - Authorization: `Bearer ${appToken}`, - }, - hooks: { - afterResponse: [validateStatusCode], - }, + const requestor = makeRequest( + `/spaces/${spaceId}/environments/${environmentId}/app_installations/${appInstallationId}/access_tokens`, + { + method: 'POST', + headers: { + Authorization: `Bearer ${appToken}`, }, - ) - .json<{ token: string }>() + }, + fetchOptions, + ) + const hookRequestor = withHook(requestor, validateStatusCode) + const retryRequestor = withRetry(hookRequestor, fetchOptions) + const response = await retryRequestor() log( `Successfully retrieved CMA Token for app ${appInstallationId} in space ${spaceId} and environment ${environmentId}`, ) - return response.token + return ((await response.json()) as { token: string }).token } /** @@ -85,7 +80,7 @@ const getTokenFromOneTimeToken = async ( */ export const createGetManagementToken = ( log: Logger, - http: HttpClient, + fetchOptions: FetchOptions, cache: LRUCache, ) => { return async (privateKey: unknown, opts: GetManagementTokenOptions): Promise => { @@ -111,7 +106,7 @@ export const createGetManagementToken = ( { appId: opts.appInstallationId, keyId: opts.keyId }, { log }, ) - const ott = await getTokenFromOneTimeToken(appToken, opts, { log, http }) + const ott = await getTokenFromOneTimeToken(appToken, opts, { log, fetchOptions }) if (opts.reuseToken) { const decoded = decode(ott) if (decoded && typeof decoded === 'object' && decoded.exp) { @@ -157,7 +152,7 @@ export const getManagementToken = async (privateKey: string, opts: GetManagement return createGetManagementToken( createLogger({ filename: __filename }), - await createHttpClient(httpClientOpts), + withDefaultOptions(httpClientOpts), defaultCache!, )(privateKey, opts) } diff --git a/src/utils/http.ts b/src/utils/http.ts index 70727382..8f1dc2c5 100644 --- a/src/utils/http.ts +++ b/src/utils/http.ts @@ -1,36 +1,63 @@ -import { - Options, - KyInstance, - HTTPError, - KyResponse, - AfterResponseHook, - KyRequest, - NormalizedOptions, -} from 'ky' - -const config = { +export class HttpError extends Error { + constructor(public response: Response) { + super(`HTTP error: ${response.status} ${response.statusText}`) + } +} +export type FetchOptions = { + prefixUrl: string + retry: { limit: number } +} +export const config: FetchOptions = { prefixUrl: process.env.BASE_URL || 'https://api.contentful.com', retry: { limit: 3 }, } - -export const createHttpClient = async (configOverride: Options = {}) => { - const { default: ky } = await import('ky') - return ky.extend({ ...config, ...configOverride }) +export const withDefaultOptions = (fetchOptions: Partial) => { + return { ...config, ...fetchOptions } } - -export const createValidateStatusCode = - (allowedStatusCodes: number[]): AfterResponseHook => - (request: KyRequest, options: NormalizedOptions, response: KyResponse) => { - if (!allowedStatusCodes.includes(response.status)) { - console.log(response.body) - throw new HTTPError(response, request, options) +type Requestor = () => Promise +export const makeRequest = ( + url: string, + options: RequestInit, + fetchOptions: FetchOptions, +): Requestor => { + return async (): Promise => { + const response = await fetch(`${fetchOptions.prefixUrl}${url}`, options) + if (!response.ok) { + throw new HttpError(response) } return response } +} + +// eslint-disable-next-line no-unused-vars +type Hook = (response: Response) => Response +export const withHook = (requestor: Requestor, hook: Hook): Requestor => { + return async (): Promise => { + const response = await requestor() + return hook(response) + } +} -export { HTTPError as HttpError } +export const withRetry = (requestor: Requestor, fetchOptions: FetchOptions): Requestor => { + return async (): Promise => { + let lastError: Error | null = null + let retries = 0 + do { + try { + return await requestor() + } catch (error) { + lastError = error as Error + retries++ + } + } while (retries <= fetchOptions.retry.limit) + throw lastError + } +} -export type HttpClient = KyInstance -export type Request = KyRequest -export type Response = KyResponse -export type ErrorOptions = NormalizedOptions +export const createValidateStatusCode = (allowedStatusCodes: number[]) => (response: Response) => { + if (!allowedStatusCodes.includes(response.status)) { + console.log(response.body) + throw new HttpError(response) + } + return response +} diff --git a/src/utils/index.ts b/src/utils/index.ts index a759a8b8..c9f92a53 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,4 +1,3 @@ -export type { Response, HttpClient, Request, ErrorOptions } from './http' -export { createHttpClient, createValidateStatusCode, HttpError } from './http' +export { createValidateStatusCode, HttpError } from './http' export { createLogger } from './logger' export type { Logger } from './logger' diff --git a/test/integration/keys.test.ts b/test/integration/keys.test.ts index 5901bbdf..3e5f1dbd 100644 --- a/test/integration/keys.test.ts +++ b/test/integration/keys.test.ts @@ -5,7 +5,7 @@ import * as assert from 'assert' //TODO use built version import { getManagementToken } from '../../src/keys' import { cleanOldKeys, setPublicKey } from '../utils' -import { createHttpClient } from '../../src/utils' +import { config, makeRequest } from '../../src/utils/http' describe('Keys Utilities', () => { before(async () => { @@ -32,14 +32,19 @@ describe('Keys Utilities', () => { environmentId, }) - await assert.doesNotReject(async () => { - const http = await createHttpClient() - - return http.get(`spaces/${spaceId}/entries`, { - headers: { - Authorization: `Bearer ${token}`, + await assert.doesNotReject(() => { + const requestor = makeRequest( + `/spaces/${spaceId}/entries`, + { + method: 'GET', + headers: { + Authorization: `Bearer ${token}`, + }, }, - }) + config, + ) + + return requestor() }) }) }) diff --git a/test/utils.ts b/test/utils.ts index 84756115..57831b2d 100644 --- a/test/utils.ts +++ b/test/utils.ts @@ -2,29 +2,39 @@ import * as crypto from 'crypto' import base64url from 'base64url' -import { createHttpClient, createValidateStatusCode } from '../src/utils' - -const httpFactory = async () => - await createHttpClient({ - headers: { - Authorization: `Bearer ${process.env.PERSONAL_ACCESS_TOKEN}`, - }, - }) +import { createValidateStatusCode } from '../src/utils' +import { config, makeRequest, withHook } from '../src/utils/http' export const cleanOldKeys = async () => { const organizationId = process.env.ORGANIZATION_ID const appDefinitionId = process.env.APP_ID - const http = await httpFactory() - const { items } = await http - .get(`organizations/${organizationId}/app_definitions/${appDefinitionId}/keys`) - .json<{ items: { jwk: { x5t: string } }[] }>() + const requestor = makeRequest( + `/organizations/${organizationId}/app_definitions/${appDefinitionId}/keys`, + { + method: 'GET', + headers: { + Authorization: `Bearer ${process.env.PERSONAL_ACCESS_TOKEN}`, + }, + }, + config, + ) + const response = await requestor() + const { items } = (await response.json()) as { items: { jwk: { x5t: string } }[] } const fingerprints = items.map((i: any) => i.jwk.x5t) const deleteKeysRequests = fingerprints.map((fingerprint: string) => { - return http.delete( - `organizations/${organizationId}/app_definitions/${appDefinitionId}/keys/${fingerprint}`, + const requestor = makeRequest( + `/organizations/${organizationId}/app_definitions/${appDefinitionId}/keys/${fingerprint}`, + { + method: 'DELETE', + headers: { + Authorization: `Bearer ${process.env.PERSONAL_ACCESS_TOKEN}`, + }, + }, + config, ) + return requestor() }) return Promise.all(deleteKeysRequests) @@ -35,20 +45,26 @@ export const setPublicKey = async (publicKey: Buffer) => { const appDefinitionId = process.env.APP_ID const keyId = base64url(crypto.createHash('sha256').update(publicKey).digest()) - const http = await httpFactory() - return http.post(`organizations/${organizationId}/app_definitions/${appDefinitionId}/keys`, { - json: { - jwk: { - kty: 'RSA', - use: 'sig', - alg: 'RS256', - x5c: [publicKey.toString('base64')], - kid: keyId, - x5t: keyId, + const requestor = makeRequest( + `/organizations/${organizationId}/app_definitions/${appDefinitionId}/keys`, + { + method: 'POST', + headers: { + Authorization: `Bearer ${process.env.PERSONAL_ACCESS_TOKEN}`, }, + body: JSON.stringify({ + jwk: { + kty: 'RSA', + use: 'sig', + alg: 'RS256', + x5c: [publicKey.toString('base64')], + kid: keyId, + x5t: keyId, + }, + }), }, - hooks: { - afterResponse: [createValidateStatusCode([201, 200])], - }, - }) + config, + ) + const hookRequestor = withHook(requestor, createValidateStatusCode([201, 200])) + return hookRequestor() } diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json new file mode 100644 index 00000000..f25ce8c3 --- /dev/null +++ b/tsconfig.eslint.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "include": ["./src/**/*", "./src/**/*.spec.ts", "./test/**/*.test.ts"], + "exclude": [], + "compilerOptions": { + "lib": ["es2020", "esnext", "dom"] + } + } \ No newline at end of file From 5b535220f9208a5c9a1860590ff7b3598d550f1d Mon Sep 17 00:00:00 2001 From: "contentful-automation[bot]" <100587065+contentful-automation[bot]@users.noreply.github.com> Date: Fri, 26 Sep 2025 22:54:53 +0000 Subject: [PATCH 06/10] chore(release): 3.14.0-next.1 [skip ci] # [3.14.0-next.1](https://github.com/contentful/node-apps-toolkit/compare/v3.13.2-next.1...v3.14.0-next.1) (2025-09-26) ### Bug Fixes * cjs compat ([4f24813](https://github.com/contentful/node-apps-toolkit/commit/4f248134660de9c32d7a61f481068dc3a2c5144e)) * cloudflare compliant [EXT-6803] ([8ede9d1](https://github.com/contentful/node-apps-toolkit/commit/8ede9d19480e9cb943d9fe336ed3f4f213580e80)) ### Features * swap got for ky ([2f42033](https://github.com/contentful/node-apps-toolkit/commit/2f42033604a0ce8f7e702eaf100c4d31fa426ef6)) --- CHANGELOG.md | 13 +++++++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 16 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 99637c15..1cb10795 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +# [3.14.0-next.1](https://github.com/contentful/node-apps-toolkit/compare/v3.13.2-next.1...v3.14.0-next.1) (2025-09-26) + + +### Bug Fixes + +* cjs compat ([4f24813](https://github.com/contentful/node-apps-toolkit/commit/4f248134660de9c32d7a61f481068dc3a2c5144e)) +* cloudflare compliant [EXT-6803] ([8ede9d1](https://github.com/contentful/node-apps-toolkit/commit/8ede9d19480e9cb943d9fe336ed3f4f213580e80)) + + +### Features + +* swap got for ky ([2f42033](https://github.com/contentful/node-apps-toolkit/commit/2f42033604a0ce8f7e702eaf100c4d31fa426ef6)) + ## [3.13.2-next.1](https://github.com/contentful/node-apps-toolkit/compare/v3.13.1...v3.13.2-next.1) (2025-09-26) diff --git a/package-lock.json b/package-lock.json index 9d180d87..ca8af7fe 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@contentful/node-apps-toolkit", - "version": "3.13.2-next.1", + "version": "3.14.0-next.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@contentful/node-apps-toolkit", - "version": "3.13.2-next.1", + "version": "3.14.0-next.1", "license": "MIT", "dependencies": { "@types/debug": "^4.1.5", diff --git a/package.json b/package.json index 30921ec0..5ff57ecb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentful/node-apps-toolkit", - "version": "3.13.2-next.1", + "version": "3.14.0-next.1", "description": "A collection of helpers and utilities for creating NodeJS Contentful Apps", "main": "lib/index.cjs", "module": "lib/index.mjs", From 01d85499c344ecdfecc3c0d248ef2cab4e470b87 Mon Sep 17 00:00:00 2001 From: Bob Hemphill Date: Fri, 26 Sep 2025 19:58:52 -0600 Subject: [PATCH 07/10] fix: remove logger --- src/keys/get-management-token.spec.ts | 24 +++++++++++----------- src/keys/get-management-token.ts | 29 ++++++++++++++------------- 2 files changed, 27 insertions(+), 26 deletions(-) diff --git a/src/keys/get-management-token.spec.ts b/src/keys/get-management-token.spec.ts index cab1eded..a0a5b053 100644 --- a/src/keys/get-management-token.spec.ts +++ b/src/keys/get-management-token.spec.ts @@ -10,7 +10,7 @@ import { GetManagementTokenOptions, } from './get-management-token' import { HttpError } from '../utils' -import { Logger } from '../utils' +// import { Logger } from '../utils' import { sign } from 'jsonwebtoken' import { LRUCache } from 'lru-cache' @@ -24,7 +24,7 @@ const DEFAULT_OPTIONS: GetManagementTokenOptions = { environmentId: ENVIRONMENT_ID, reuseToken: false, } -const noop = () => {} +// const noop = () => {} const defaultCache: LRUCache = new LRUCache({ max: 10 }) let fetchStub: sinon.SinonStub @@ -40,10 +40,10 @@ afterEach(() => { describe('getManagementToken', () => { it('fetches a token', async () => { const mockToken = 'token' - const logger = noop as unknown as Logger + // const logger = noop as unknown as Logger fetchStub.resolves({ ok: true, status: 201, json: () => Promise.resolve({ token: mockToken }) }) const getManagementToken = createGetManagementToken( - logger, + // logger, { prefixUrl: '', retry: { limit: 0 } }, defaultCache, ) @@ -62,14 +62,14 @@ describe('getManagementToken', () => { }) it('caches token while valid', async () => { - const logger = noop as unknown as Logger + // const logger = noop as unknown as Logger const mockToken = sign({ a: 'b' }, 'a-secret-key', { expiresIn: '10 minutes', }) fetchStub.resolves({ ok: true, status: 201, json: () => Promise.resolve({ token: mockToken }) }) const getManagementToken = createGetManagementToken( - logger, + // logger, { prefixUrl: '', retry: { limit: 0 } }, defaultCache, ) @@ -84,7 +84,7 @@ describe('getManagementToken', () => { }) it('does not cache expired token', async () => { - const logger = noop as unknown as Logger + // const logger = noop as unknown as Logger const mockToken = sign({ a: 'b' }, 'a-secret-key', { expiresIn: '5 minutes', }) @@ -92,7 +92,7 @@ describe('getManagementToken', () => { fetchStub.resolves({ ok: true, status: 201, json: () => Promise.resolve({ token: mockToken }) }) const cache: LRUCache = new LRUCache({ max: 10 }) const getManagementToken = createGetManagementToken( - logger, + // logger, { prefixUrl: '', retry: { limit: 0 } }, cache, ) @@ -118,14 +118,14 @@ describe('getManagementToken', () => { describe('when using a keyId', () => { it('fetches a token', async () => { const mockToken = 'token' - const logger = noop as unknown as Logger + // const logger = noop as unknown as Logger fetchStub.resolves({ ok: true, status: 201, json: () => Promise.resolve({ token: mockToken }), }) const getManagementToken = createGetManagementToken( - logger, + // logger, { prefixUrl: '', retry: { limit: 0 } }, defaultCache, ) @@ -158,10 +158,10 @@ describe('getManagementToken', () => { describe('when having API problems', () => { it(`throws when API returns an error`, async () => { - const logger = noop as unknown as Logger + // const logger = noop as unknown as Logger fetchStub.rejects(new HttpError({ statusCode: 500 } as unknown as Response)) const getManagementToken = createGetManagementToken( - logger, + // logger, { prefixUrl: '', retry: { limit: 0 } }, defaultCache, ) diff --git a/src/keys/get-management-token.ts b/src/keys/get-management-token.ts index bf7f7d27..1033b409 100644 --- a/src/keys/get-management-token.ts +++ b/src/keys/get-management-token.ts @@ -1,7 +1,7 @@ import * as jwtImpl from 'jsonwebtoken' import type { SignOptions } from 'jsonwebtoken' import { LRUCache } from 'lru-cache' -import { createLogger, Logger, createValidateStatusCode } from '../utils' +import { createValidateStatusCode } from '../utils' import { FetchOptions, makeRequest, withDefaultOptions, withHook, withRetry } from '../utils/http' const jwt = 'default' in jwtImpl ? jwtImpl.default : jwtImpl @@ -24,18 +24,19 @@ let defaultCache: LRUCache | undefined const generateOneTimeToken = ( privateKey: string, { appId, keyId }: { appId: string; keyId?: string }, - { log }: { log: Logger }, + // { log }: { log: Logger }, ): string => { - log('Signing a JWT token with private key') + // log('Signing a JWT token with private key') + // eslint-disable-next-line no-useless-catch try { const baseSignOptions: SignOptions = { algorithm: 'RS256', issuer: appId, expiresIn: '10m' } const signOptions: SignOptions = keyId ? { ...baseSignOptions, keyid: keyId } : baseSignOptions const token = sign({}, privateKey, signOptions) - log('Successfully signed token') + // log('Successfully signed token') return token } catch (e) { - log('Unable to sign token') + // log('Unable to sign token') throw e } } @@ -47,11 +48,11 @@ const getTokenFromOneTimeToken = async ( spaceId, environmentId, }: { appInstallationId: string; spaceId: string; environmentId: string }, - { log, fetchOptions }: { log: Logger; fetchOptions: FetchOptions }, + { /* log, */ fetchOptions }: { /* log: Logger; */ fetchOptions: FetchOptions }, ): Promise => { const validateStatusCode = createValidateStatusCode([201]) - log(`Requesting CMA Token with given App Token`) + // log(`Requesting CMA Token with given App Token`) const requestor = makeRequest( `/spaces/${spaceId}/environments/${environmentId}/app_installations/${appInstallationId}/access_tokens`, @@ -67,9 +68,9 @@ const getTokenFromOneTimeToken = async ( const retryRequestor = withRetry(hookRequestor, fetchOptions) const response = await retryRequestor() - log( - `Successfully retrieved CMA Token for app ${appInstallationId} in space ${spaceId} and environment ${environmentId}`, - ) + // log( + // `Successfully retrieved CMA Token for app ${appInstallationId} in space ${spaceId} and environment ${environmentId}`, + // ) return ((await response.json()) as { token: string }).token } @@ -79,7 +80,7 @@ const getTokenFromOneTimeToken = async ( * @internal */ export const createGetManagementToken = ( - log: Logger, + // log: Logger, fetchOptions: FetchOptions, cache: LRUCache, ) => { @@ -104,9 +105,9 @@ export const createGetManagementToken = ( const appToken = generateOneTimeToken( privateKey, { appId: opts.appInstallationId, keyId: opts.keyId }, - { log }, + // { log }, ) - const ott = await getTokenFromOneTimeToken(appToken, opts, { log, fetchOptions }) + const ott = await getTokenFromOneTimeToken(appToken, opts, { /* log, */ fetchOptions }) if (opts.reuseToken) { const decoded = decode(ott) if (decoded && typeof decoded === 'object' && decoded.exp) { @@ -151,7 +152,7 @@ export const getManagementToken = async (privateKey: string, opts: GetManagement const httpClientOpts = typeof opts.host !== 'undefined' ? { prefixUrl: opts.host } : {} return createGetManagementToken( - createLogger({ filename: __filename }), + // createLogger({ filename: __filename }), withDefaultOptions(httpClientOpts), defaultCache!, )(privateKey, opts) From 638c786186dc392fbf1ed12abac61ef62eac684b Mon Sep 17 00:00:00 2001 From: Bob Hemphill Date: Fri, 26 Sep 2025 21:54:00 -0600 Subject: [PATCH 08/10] fix: simplified logger with explicit namespacing --- src/keys/get-management-token.spec.ts | 24 +++++++++++----------- src/keys/get-management-token.ts | 29 +++++++++++++-------------- src/utils/logger.ts | 14 +++---------- 3 files changed, 29 insertions(+), 38 deletions(-) diff --git a/src/keys/get-management-token.spec.ts b/src/keys/get-management-token.spec.ts index a0a5b053..cab1eded 100644 --- a/src/keys/get-management-token.spec.ts +++ b/src/keys/get-management-token.spec.ts @@ -10,7 +10,7 @@ import { GetManagementTokenOptions, } from './get-management-token' import { HttpError } from '../utils' -// import { Logger } from '../utils' +import { Logger } from '../utils' import { sign } from 'jsonwebtoken' import { LRUCache } from 'lru-cache' @@ -24,7 +24,7 @@ const DEFAULT_OPTIONS: GetManagementTokenOptions = { environmentId: ENVIRONMENT_ID, reuseToken: false, } -// const noop = () => {} +const noop = () => {} const defaultCache: LRUCache = new LRUCache({ max: 10 }) let fetchStub: sinon.SinonStub @@ -40,10 +40,10 @@ afterEach(() => { describe('getManagementToken', () => { it('fetches a token', async () => { const mockToken = 'token' - // const logger = noop as unknown as Logger + const logger = noop as unknown as Logger fetchStub.resolves({ ok: true, status: 201, json: () => Promise.resolve({ token: mockToken }) }) const getManagementToken = createGetManagementToken( - // logger, + logger, { prefixUrl: '', retry: { limit: 0 } }, defaultCache, ) @@ -62,14 +62,14 @@ describe('getManagementToken', () => { }) it('caches token while valid', async () => { - // const logger = noop as unknown as Logger + const logger = noop as unknown as Logger const mockToken = sign({ a: 'b' }, 'a-secret-key', { expiresIn: '10 minutes', }) fetchStub.resolves({ ok: true, status: 201, json: () => Promise.resolve({ token: mockToken }) }) const getManagementToken = createGetManagementToken( - // logger, + logger, { prefixUrl: '', retry: { limit: 0 } }, defaultCache, ) @@ -84,7 +84,7 @@ describe('getManagementToken', () => { }) it('does not cache expired token', async () => { - // const logger = noop as unknown as Logger + const logger = noop as unknown as Logger const mockToken = sign({ a: 'b' }, 'a-secret-key', { expiresIn: '5 minutes', }) @@ -92,7 +92,7 @@ describe('getManagementToken', () => { fetchStub.resolves({ ok: true, status: 201, json: () => Promise.resolve({ token: mockToken }) }) const cache: LRUCache = new LRUCache({ max: 10 }) const getManagementToken = createGetManagementToken( - // logger, + logger, { prefixUrl: '', retry: { limit: 0 } }, cache, ) @@ -118,14 +118,14 @@ describe('getManagementToken', () => { describe('when using a keyId', () => { it('fetches a token', async () => { const mockToken = 'token' - // const logger = noop as unknown as Logger + const logger = noop as unknown as Logger fetchStub.resolves({ ok: true, status: 201, json: () => Promise.resolve({ token: mockToken }), }) const getManagementToken = createGetManagementToken( - // logger, + logger, { prefixUrl: '', retry: { limit: 0 } }, defaultCache, ) @@ -158,10 +158,10 @@ describe('getManagementToken', () => { describe('when having API problems', () => { it(`throws when API returns an error`, async () => { - // const logger = noop as unknown as Logger + const logger = noop as unknown as Logger fetchStub.rejects(new HttpError({ statusCode: 500 } as unknown as Response)) const getManagementToken = createGetManagementToken( - // logger, + logger, { prefixUrl: '', retry: { limit: 0 } }, defaultCache, ) diff --git a/src/keys/get-management-token.ts b/src/keys/get-management-token.ts index 1033b409..27fe3bf5 100644 --- a/src/keys/get-management-token.ts +++ b/src/keys/get-management-token.ts @@ -1,7 +1,7 @@ import * as jwtImpl from 'jsonwebtoken' import type { SignOptions } from 'jsonwebtoken' import { LRUCache } from 'lru-cache' -import { createValidateStatusCode } from '../utils' +import { createLogger, createValidateStatusCode, Logger } from '../utils' import { FetchOptions, makeRequest, withDefaultOptions, withHook, withRetry } from '../utils/http' const jwt = 'default' in jwtImpl ? jwtImpl.default : jwtImpl @@ -24,19 +24,18 @@ let defaultCache: LRUCache | undefined const generateOneTimeToken = ( privateKey: string, { appId, keyId }: { appId: string; keyId?: string }, - // { log }: { log: Logger }, + { log }: { log: Logger }, ): string => { - // log('Signing a JWT token with private key') - // eslint-disable-next-line no-useless-catch + log('Signing a JWT token with private key') try { const baseSignOptions: SignOptions = { algorithm: 'RS256', issuer: appId, expiresIn: '10m' } const signOptions: SignOptions = keyId ? { ...baseSignOptions, keyid: keyId } : baseSignOptions const token = sign({}, privateKey, signOptions) - // log('Successfully signed token') + log('Successfully signed token') return token } catch (e) { - // log('Unable to sign token') + log('Unable to sign token') throw e } } @@ -48,11 +47,11 @@ const getTokenFromOneTimeToken = async ( spaceId, environmentId, }: { appInstallationId: string; spaceId: string; environmentId: string }, - { /* log, */ fetchOptions }: { /* log: Logger; */ fetchOptions: FetchOptions }, + { log, fetchOptions }: { log: Logger; fetchOptions: FetchOptions }, ): Promise => { const validateStatusCode = createValidateStatusCode([201]) - // log(`Requesting CMA Token with given App Token`) + log(`Requesting CMA Token with given App Token`) const requestor = makeRequest( `/spaces/${spaceId}/environments/${environmentId}/app_installations/${appInstallationId}/access_tokens`, @@ -68,9 +67,9 @@ const getTokenFromOneTimeToken = async ( const retryRequestor = withRetry(hookRequestor, fetchOptions) const response = await retryRequestor() - // log( - // `Successfully retrieved CMA Token for app ${appInstallationId} in space ${spaceId} and environment ${environmentId}`, - // ) + log( + `Successfully retrieved CMA Token for app ${appInstallationId} in space ${spaceId} and environment ${environmentId}`, + ) return ((await response.json()) as { token: string }).token } @@ -80,7 +79,7 @@ const getTokenFromOneTimeToken = async ( * @internal */ export const createGetManagementToken = ( - // log: Logger, + log: Logger, fetchOptions: FetchOptions, cache: LRUCache, ) => { @@ -105,9 +104,9 @@ export const createGetManagementToken = ( const appToken = generateOneTimeToken( privateKey, { appId: opts.appInstallationId, keyId: opts.keyId }, - // { log }, + { log }, ) - const ott = await getTokenFromOneTimeToken(appToken, opts, { /* log, */ fetchOptions }) + const ott = await getTokenFromOneTimeToken(appToken, opts, { log, fetchOptions }) if (opts.reuseToken) { const decoded = decode(ott) if (decoded && typeof decoded === 'object' && decoded.exp) { @@ -152,7 +151,7 @@ export const getManagementToken = async (privateKey: string, opts: GetManagement const httpClientOpts = typeof opts.host !== 'undefined' ? { prefixUrl: opts.host } : {} return createGetManagementToken( - // createLogger({ filename: __filename }), + createLogger({ namespace: 'get-management-token' }), withDefaultOptions(httpClientOpts), defaultCache!, )(privateKey, opts) diff --git a/src/utils/logger.ts b/src/utils/logger.ts index d3de9987..5f45eaf4 100644 --- a/src/utils/logger.ts +++ b/src/utils/logger.ts @@ -1,20 +1,12 @@ -import * as path from 'path' import debug from 'debug' -const SRC_PATH = path.join(__dirname, '..') -const { name: APP_NAME } = require('../../package.json') - -const getNamespaceFromFilename = (filename: string) => { - return filename.split(SRC_PATH)[1].slice(0, -3) -} +const APP_NAME = '@contentful-node-apps-toolkit' /** * @internal */ -export const createLogger = (opts: { namespace: string } | { filename: string }) => { - const ns = 'namespace' in opts ? opts.namespace : getNamespaceFromFilename(opts.filename) - - return debug(APP_NAME).extend(ns) +export const createLogger = (opts: { namespace: string }) => { + return debug(APP_NAME).extend(opts.namespace) } export type Logger = debug.Debugger From de60cd4329e425508d923d3f4166fa13e86cd101 Mon Sep 17 00:00:00 2001 From: "contentful-automation[bot]" <100587065+contentful-automation[bot]@users.noreply.github.com> Date: Sat, 27 Sep 2025 03:59:54 +0000 Subject: [PATCH 09/10] chore(release): 3.14.0-next.2 [skip ci] # [3.14.0-next.2](https://github.com/contentful/node-apps-toolkit/compare/v3.14.0-next.1...v3.14.0-next.2) (2025-09-27) ### Bug Fixes * remove logger ([01d8549](https://github.com/contentful/node-apps-toolkit/commit/01d85499c344ecdfecc3c0d248ef2cab4e470b87)) * simplified logger with explicit namespacing ([638c786](https://github.com/contentful/node-apps-toolkit/commit/638c786186dc392fbf1ed12abac61ef62eac684b)) --- CHANGELOG.md | 8 ++++++++ package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1cb10795..a5cd03be 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,11 @@ +# [3.14.0-next.2](https://github.com/contentful/node-apps-toolkit/compare/v3.14.0-next.1...v3.14.0-next.2) (2025-09-27) + + +### Bug Fixes + +* remove logger ([01d8549](https://github.com/contentful/node-apps-toolkit/commit/01d85499c344ecdfecc3c0d248ef2cab4e470b87)) +* simplified logger with explicit namespacing ([638c786](https://github.com/contentful/node-apps-toolkit/commit/638c786186dc392fbf1ed12abac61ef62eac684b)) + # [3.14.0-next.1](https://github.com/contentful/node-apps-toolkit/compare/v3.13.2-next.1...v3.14.0-next.1) (2025-09-26) diff --git a/package-lock.json b/package-lock.json index ca8af7fe..c283b0ce 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@contentful/node-apps-toolkit", - "version": "3.14.0-next.1", + "version": "3.14.0-next.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@contentful/node-apps-toolkit", - "version": "3.14.0-next.1", + "version": "3.14.0-next.2", "license": "MIT", "dependencies": { "@types/debug": "^4.1.5", diff --git a/package.json b/package.json index 5ff57ecb..bd8c30e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentful/node-apps-toolkit", - "version": "3.14.0-next.1", + "version": "3.14.0-next.2", "description": "A collection of helpers and utilities for creating NodeJS Contentful Apps", "main": "lib/index.cjs", "module": "lib/index.mjs", From 4158d6f666bb8665523422415faa604fa21fbfb7 Mon Sep 17 00:00:00 2001 From: Bob Hemphill Date: Sat, 27 Sep 2025 14:07:09 -0600 Subject: [PATCH 10/10] fix: tsup esm + cjs config with jose --- .eslintrc.js | 12 +- package-lock.json | 2215 +++++++++++++++++-------- package.json | 14 +- src/keys/get-management-token.spec.ts | 56 +- src/keys/get-management-token.ts | 35 +- src/requests/verify-request.spec.ts | 38 +- test/integration/keys.test.ts | 8 +- tsconfig.eslint.json | 2 +- tsup.config.js | 29 +- vitest.config.ts | 11 + vitest.setup.ts | 7 + 11 files changed, 1653 insertions(+), 774 deletions(-) create mode 100644 vitest.config.ts create mode 100644 vitest.setup.ts diff --git a/.eslintrc.js b/.eslintrc.js index bd8ac53e..097a120f 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -2,13 +2,23 @@ module.exports = { parser: '@typescript-eslint/parser', env: { node: true, - mocha: true, + es2020: true, }, parserOptions: { project: './tsconfig.eslint.json', }, plugins: ['@typescript-eslint', 'prettier'], extends: ['eslint:recommended', 'plugin:prettier/recommended'], + globals: { + describe: 'readonly', + it: 'readonly', + expect: 'readonly', + beforeAll: 'readonly', + beforeEach: 'readonly', + afterAll: 'readonly', + afterEach: 'readonly', + vi: 'readonly', + }, rules: { 'no-unused-vars': ['error', { ignoreRestSiblings: true }], }, diff --git a/package-lock.json b/package-lock.json index c283b0ce..d1b1a066 100644 --- a/package-lock.json +++ b/package-lock.json @@ -12,20 +12,18 @@ "@types/debug": "^4.1.5", "contentful-management": "^11.6.1", "debug": "^4.2.0", - "jsonwebtoken": "^9.0.0", - "ky": "^1.10.0", + "jose": "^6.1.0", "lru-cache": "^10.4.3", "runtypes": "^5.0.1" }, "devDependencies": { "@semantic-release/changelog": "6.0.3", "@semantic-release/git": "10.0.1", - "@types/jsonwebtoken": "9.0.6", - "@types/mocha": "10.0.6", "@types/node": "^22.18.6", "@types/sinon": "17.0.3", "@typescript-eslint/eslint-plugin": "7.10.0", "@typescript-eslint/parser": "7.10.0", + "@vitest/ui": "^3.2.4", "base64url": "3.0.1", "dotenv": "16.4.5", "eslint": "8.57.0", @@ -33,7 +31,6 @@ "eslint-plugin-prettier": "^5.0.0", "husky": "9.0.11", "lint-staged": "15.2.10", - "mocha": "10.4.0", "prettier": "3.2.5", "semantic-release": "23.1.1", "serve": "14.2.4", @@ -41,7 +38,8 @@ "ts-node": "10.9.2", "tsup": "^8.3.5", "typedoc": "0.25.13", - "typescript": "5.4.5" + "typescript": "5.4.5", + "vitest": "^3.2.4" }, "engines": { "node": ">=18" @@ -543,6 +541,23 @@ "node": ">=18" } }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", + "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, "node_modules/@esbuild/sunos-x64": { "version": "0.24.2", "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz", @@ -893,10 +908,11 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", @@ -1151,10 +1167,17 @@ "node": ">=12" } }, + "node_modules/@polka/url": { + "version": "1.0.0-next.29", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz", + "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==", + "dev": true, + "license": "MIT" + }, "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.29.1.tgz", - "integrity": "sha512-ssKhA8RNltTZLpG6/QNkCSge+7mBQGUqJRisZ2MDQcEGaK93QESEgWK2iOpIDZ7k9zPVkG5AS3ksvD5ZWxmItw==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.3.tgz", + "integrity": "sha512-h6cqHGZ6VdnwliFG1NXvMPTy/9PS3h8oLh7ImwR+kl+oYnQizgjxsONmmPSb2C66RksfkfIxEVtDSEcJiO0tqw==", "cpu": [ "arm" ], @@ -1166,9 +1189,9 @@ ] }, "node_modules/@rollup/rollup-android-arm64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.29.1.tgz", - "integrity": "sha512-CaRfrV0cd+NIIcVVN/jx+hVLN+VRqnuzLRmfmlzpOzB87ajixsN/+9L5xNmkaUUvEbI5BmIKS+XTwXsHEb65Ew==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.52.3.tgz", + "integrity": "sha512-wd+u7SLT/u6knklV/ifG7gr5Qy4GUbH2hMWcDauPFJzmCZUAJ8L2bTkVXC2niOIxp8lk3iH/QX8kSrUxVZrOVw==", "cpu": [ "arm64" ], @@ -1180,9 +1203,9 @@ ] }, "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.29.1.tgz", - "integrity": "sha512-2ORr7T31Y0Mnk6qNuwtyNmy14MunTAMx06VAPI6/Ju52W10zk1i7i5U3vlDRWjhOI5quBcrvhkCHyF76bI7kEw==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.52.3.tgz", + "integrity": "sha512-lj9ViATR1SsqycwFkJCtYfQTheBdvlWJqzqxwc9f2qrcVrQaF/gCuBRTiTolkRWS6KvNxSk4KHZWG7tDktLgjg==", "cpu": [ "arm64" ], @@ -1194,9 +1217,9 @@ ] }, "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.29.1.tgz", - "integrity": "sha512-j/Ej1oanzPjmN0tirRd5K2/nncAhS9W6ICzgxV+9Y5ZsP0hiGhHJXZ2JQ53iSSjj8m6cRY6oB1GMzNn2EUt6Ng==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.52.3.tgz", + "integrity": "sha512-+Dyo7O1KUmIsbzx1l+4V4tvEVnVQqMOIYtrxK7ncLSknl1xnMHLgn7gddJVrYPNZfEB8CIi3hK8gq8bDhb3h5A==", "cpu": [ "x64" ], @@ -1208,9 +1231,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.29.1.tgz", - "integrity": "sha512-91C//G6Dm/cv724tpt7nTyP+JdN12iqeXGFM1SqnljCmi5yTXriH7B1r8AD9dAZByHpKAumqP1Qy2vVNIdLZqw==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.52.3.tgz", + "integrity": "sha512-u9Xg2FavYbD30g3DSfNhxgNrxhi6xVG4Y6i9Ur1C7xUuGDW3banRbXj+qgnIrwRN4KeJ396jchwy9bCIzbyBEQ==", "cpu": [ "arm64" ], @@ -1222,9 +1245,9 @@ ] }, "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.29.1.tgz", - "integrity": "sha512-hEioiEQ9Dec2nIRoeHUP6hr1PSkXzQaCUyqBDQ9I9ik4gCXQZjJMIVzoNLBRGet+hIUb3CISMh9KXuCcWVW/8w==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.52.3.tgz", + "integrity": "sha512-5M8kyi/OX96wtD5qJR89a/3x5x8x5inXBZO04JWhkQb2JWavOWfjgkdvUqibGJeNNaz1/Z1PPza5/tAPXICI6A==", "cpu": [ "x64" ], @@ -1236,9 +1259,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.29.1.tgz", - "integrity": "sha512-Py5vFd5HWYN9zxBv3WMrLAXY3yYJ6Q/aVERoeUFwiDGiMOWsMs7FokXihSOaT/PMWUty/Pj60XDQndK3eAfE6A==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.52.3.tgz", + "integrity": "sha512-IoerZJ4l1wRMopEHRKOO16e04iXRDyZFZnNZKrWeNquh5d6bucjezgd+OxG03mOMTnS1x7hilzb3uURPkJ0OfA==", "cpu": [ "arm" ], @@ -1250,9 +1273,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.29.1.tgz", - "integrity": "sha512-RiWpGgbayf7LUcuSNIbahr0ys2YnEERD4gYdISA06wa0i8RALrnzflh9Wxii7zQJEB2/Eh74dX4y/sHKLWp5uQ==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.52.3.tgz", + "integrity": "sha512-ZYdtqgHTDfvrJHSh3W22TvjWxwOgc3ThK/XjgcNGP2DIwFIPeAPNsQxrJO5XqleSlgDux2VAoWQ5iJrtaC1TbA==", "cpu": [ "arm" ], @@ -1264,9 +1287,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.29.1.tgz", - "integrity": "sha512-Z80O+taYxTQITWMjm/YqNoe9d10OX6kDh8X5/rFCMuPqsKsSyDilvfg+vd3iXIqtfmp+cnfL1UrYirkaF8SBZA==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.52.3.tgz", + "integrity": "sha512-NcViG7A0YtuFDA6xWSgmFb6iPFzHlf5vcqb2p0lGEbT+gjrEEz8nC/EeDHvx6mnGXnGCC1SeVV+8u+smj0CeGQ==", "cpu": [ "arm64" ], @@ -1278,9 +1301,9 @@ ] }, "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.29.1.tgz", - "integrity": "sha512-fOHRtF9gahwJk3QVp01a/GqS4hBEZCV1oKglVVq13kcK3NeVlS4BwIFzOHDbmKzt3i0OuHG4zfRP0YoG5OF/rA==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.52.3.tgz", + "integrity": "sha512-d3pY7LWno6SYNXRm6Ebsq0DJGoiLXTb83AIPCXl9fmtIQs/rXoS8SJxxUNtFbJ5MiOvs+7y34np77+9l4nfFMw==", "cpu": [ "arm64" ], @@ -1291,10 +1314,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.29.1.tgz", - "integrity": "sha512-5a7q3tnlbcg0OodyxcAdrrCxFi0DgXJSoOuidFUzHZ2GixZXQs6Tc3CHmlvqKAmOs5eRde+JJxeIf9DonkmYkw==", + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.52.3.tgz", + "integrity": "sha512-3y5GA0JkBuirLqmjwAKwB0keDlI6JfGYduMlJD/Rl7fvb4Ni8iKdQs1eiunMZJhwDWdCvrcqXRY++VEBbvk6Eg==", "cpu": [ "loong64" ], @@ -1305,10 +1328,10 @@ "linux" ] }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.29.1.tgz", - "integrity": "sha512-9b4Mg5Yfz6mRnlSPIdROcfw1BU22FQxmfjlp/CShWwO3LilKQuMISMTtAu/bxmmrE6A902W2cZJuzx8+gJ8e9w==", + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.52.3.tgz", + "integrity": "sha512-AUUH65a0p3Q0Yfm5oD2KVgzTKgwPyp9DSXc3UA7DtxhEb/WSPfbG4wqXeSN62OG5gSo18em4xv6dbfcUGXcagw==", "cpu": [ "ppc64" ], @@ -1320,9 +1343,23 @@ ] }, "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.29.1.tgz", - "integrity": "sha512-G5pn0NChlbRM8OJWpJFMX4/i8OEU538uiSv0P6roZcbpe/WfhEO+AT8SHVKfp8qhDQzaz7Q+1/ixMy7hBRidnQ==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.52.3.tgz", + "integrity": "sha512-1makPhFFVBqZE+XFg3Dkq+IkQ7JvmUrwwqaYBL2CE+ZpxPaqkGaiWFEWVGyvTwZace6WLJHwjVh/+CXbKDGPmg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.52.3.tgz", + "integrity": "sha512-OOFJa28dxfl8kLOPMUOQBCO6z3X2SAfzIE276fwT52uXDWUS178KWq0pL7d6p1kz7pkzA0yQwtqL0dEPoVcRWg==", "cpu": [ "riscv64" ], @@ -1334,9 +1371,9 @@ ] }, "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.29.1.tgz", - "integrity": "sha512-WM9lIkNdkhVwiArmLxFXpWndFGuOka4oJOZh8EP3Vb8q5lzdSCBuhjavJsw68Q9AKDGeOOIHYzYm4ZFvmWez5g==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.52.3.tgz", + "integrity": "sha512-jMdsML2VI5l+V7cKfZx3ak+SLlJ8fKvLJ0Eoa4b9/vCUrzXKgoKxvHqvJ/mkWhFiyp88nCkM5S2v6nIwRtPcgg==", "cpu": [ "s390x" ], @@ -1348,9 +1385,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.29.1.tgz", - "integrity": "sha512-87xYCwb0cPGZFoGiErT1eDcssByaLX4fc0z2nRM6eMtV9njAfEE6OW3UniAoDhX4Iq5xQVpE6qO9aJbCFumKYQ==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.52.3.tgz", + "integrity": "sha512-tPgGd6bY2M2LJTA1uGq8fkSPK8ZLYjDjY+ZLK9WHncCnfIz29LIXIqUgzCR0hIefzy6Hpbe8Th5WOSwTM8E7LA==", "cpu": [ "x64" ], @@ -1361,9 +1398,9 @@ ] }, "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.29.1.tgz", - "integrity": "sha512-xufkSNppNOdVRCEC4WKvlR1FBDyqCSCpQeMMgv9ZyXqqtKBfkw1yfGMTUTs9Qsl6WQbJnsGboWCp7pJGkeMhKA==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.52.3.tgz", + "integrity": "sha512-BCFkJjgk+WFzP+tcSMXq77ymAPIxsX9lFJWs+2JzuZTLtksJ2o5hvgTdIcZ5+oKzUDMwI0PfWzRBYAydAHF2Mw==", "cpu": [ "x64" ], @@ -1374,10 +1411,24 @@ "linux" ] }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.52.3.tgz", + "integrity": "sha512-KTD/EqjZF3yvRaWUJdD1cW+IQBk4fbQaHYJUmP8N4XoKFZilVL8cobFSTDnjTtxWJQ3JYaMgF4nObY/+nYkumA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.29.1.tgz", - "integrity": "sha512-F2OiJ42m77lSkizZQLuC+jiZ2cgueWQL5YC9tjo3AgaEw+KJmVxHGSyQfDUoYR9cci0lAywv2Clmckzulcq6ig==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.52.3.tgz", + "integrity": "sha512-+zteHZdoUYLkyYKObGHieibUFLbttX2r+58l27XZauq0tcWYYuKUwY2wjeCN9oK1Um2YgH2ibd6cnX/wFD7DuA==", "cpu": [ "arm64" ], @@ -1389,9 +1440,9 @@ ] }, "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.29.1.tgz", - "integrity": "sha512-rYRe5S0FcjlOBZQHgbTKNrqxCBUmgDJem/VQTCcTnA2KCabYSWQDrytOzX7avb79cAAweNmMUb/Zw18RNd4mng==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.52.3.tgz", + "integrity": "sha512-of1iHkTQSo3kr6dTIRX6t81uj/c/b15HXVsPcEElN5sS859qHrOepM5p9G41Hah+CTqSh2r8Bm56dL2z9UQQ7g==", "cpu": [ "ia32" ], @@ -1402,10 +1453,24 @@ "win32" ] }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.52.3.tgz", + "integrity": "sha512-s0hybmlHb56mWVZQj8ra9048/WZTPLILKxcvcq+8awSZmyiSUZjjem1AhU3Tf4ZKpYhK4mg36HtHDOe8QJS5PQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.29.1.tgz", - "integrity": "sha512-+10CMg9vt1MoHj6x1pxyjPSMjHTIlqs8/tBztXvPAx24SKs9jwVnKqHJumlH/IzhaPUaj3T6T6wfZr8okdXaIg==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.52.3.tgz", + "integrity": "sha512-zGIbEVVXVtauFgl3MRwGWEN36P5ZGenHRMgNw88X5wEhEBpq0XrMEZwOn07+ICrwM17XO5xfMZqh0OldCH5VTA==", "cpu": [ "x64" ], @@ -1999,6 +2064,16 @@ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", "dev": true }, + "node_modules/@types/chai": { + "version": "5.2.2", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-5.2.2.tgz", + "integrity": "sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/deep-eql": "*" + } + }, "node_modules/@types/debug": { "version": "4.1.12", "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", @@ -2007,27 +2082,19 @@ "@types/ms": "*" } }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "node_modules/@types/deep-eql": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@types/deep-eql/-/deep-eql-4.0.2.tgz", + "integrity": "sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==", "dev": true, "license": "MIT" }, - "node_modules/@types/jsonwebtoken": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.6.tgz", - "integrity": "sha512-/5hndP5dCjloafCXns6SZyESp3Ldq7YjH3zwzwczYnjxIT0Fqzk5ROSYVGfFyczIue7IUEj8hkvLbPoLQ18vQw==", + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", "dev": true, - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/mocha": { - "version": "10.0.6", - "resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.6.tgz", - "integrity": "sha512-dJvrYWxP/UcXm36Qn36fxhUKu8A/xMRXVT2cliFF1Z7UA9liG5Psj3ezNSZw+5puH2czDXRLcXQxf8JbJt0ejg==", - "dev": true + "license": "MIT" }, "node_modules/@types/ms": { "version": "0.7.34", @@ -2038,6 +2105,7 @@ "version": "22.18.6", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.18.6.tgz", "integrity": "sha512-r8uszLPpeIWbNKtvWRt/DbVi5zbqZyj1PTmhRMqBMvDnaz1QpmSKujUtJLrqGZeoM8v72MfYggDceY4K1itzWQ==", + "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.21.0" @@ -2047,6 +2115,7 @@ "version": "6.21.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, "license": "MIT" }, "node_modules/@types/normalize-package-data": { @@ -2261,6 +2330,143 @@ "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", "dev": true }, + "node_modules/@vitest/expect": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.2.4.tgz", + "integrity": "sha512-Io0yyORnB6sikFlt8QW5K7slY4OjqNX9jmJQ02QDda8lyM6B5oNgVWoSoKPac8/kgnCUzuHQKrSLtu/uOqqrig==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/mocker": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.2.4.tgz", + "integrity": "sha512-46ryTE9RZO/rfDd7pEqFl7etuyzekzEhUbTW3BvmeO/BcCMEgq59BKhek3dXDWgAj4oMK6OZi+vRr1wPW6qjEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/spy": "3.2.4", + "estree-walker": "^3.0.3", + "magic-string": "^0.30.17" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "msw": "^2.4.9", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "peerDependenciesMeta": { + "msw": { + "optional": true + }, + "vite": { + "optional": true + } + } + }, + "node_modules/@vitest/pretty-format": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.2.4.tgz", + "integrity": "sha512-IVNZik8IVRJRTr9fxlitMKeJeXFFFN0JaB9PHPGQ8NKQbGpfjlTx9zO4RefN8gp7eqjNy8nyK3NZmBzOPeIxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/runner": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.2.4.tgz", + "integrity": "sha512-oukfKT9Mk41LreEW09vt45f8wx7DordoWUZMYdY/cyAk7w5TWkTRCNZYF7sX7n2wB7jyGAl74OxgwhPgKaqDMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.2.4", + "pathe": "^2.0.3", + "strip-literal": "^3.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/snapshot": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.2.4.tgz", + "integrity": "sha512-dEYtS7qQP2CjU27QBC5oUOxLE/v5eLkGqPE0ZKEIDGMs4vKWe7IjgLOeauHsR0D5YuuycGRO5oSRXnwnmA78fQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "magic-string": "^0.30.17", + "pathe": "^2.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/spy": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.2.4.tgz", + "integrity": "sha512-vAfasCOe6AIK70iP5UD11Ac4siNUNJ9i/9PZ3NKx07sG6sUxeag1LWdNrMWeKKYBLlzuK+Gn65Yd5nyL6ds+nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "tinyspy": "^4.0.3" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, + "node_modules/@vitest/ui": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-3.2.4.tgz", + "integrity": "sha512-hGISOaP18plkzbWEcP/QvtRW1xDXF2+96HbEX6byqQhAUbiS5oH6/9JwW+QsQCIYON2bI6QZBF+2PvOmrRZ9wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/utils": "3.2.4", + "fflate": "^0.8.2", + "flatted": "^3.3.3", + "pathe": "^2.0.3", + "sirv": "^3.0.1", + "tinyglobby": "^0.2.14", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "vitest": "3.2.4" + } + }, + "node_modules/@vitest/utils": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.2.4.tgz", + "integrity": "sha512-fB2V0JFrQSMsCo9HiSq3Ezpdv4iYaXRG1Sx8edX3MwxfyNn83mKiGzOcH+Fkxt4MHxr3y42fQi1oeAInqgX2QA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vitest/pretty-format": "3.2.4", + "loupe": "^3.1.4", + "tinyrainbow": "^2.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + } + }, "node_modules/@zeit/schemas": { "version": "2.36.0", "resolved": "https://registry.npmjs.org/@zeit/schemas/-/schemas-2.36.0.tgz", @@ -2389,15 +2595,6 @@ "node": ">=8" } }, - "node_modules/ansi-colors": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.1.tgz", - "integrity": "sha512-JoX0apGbHaUJBNl6yF+p6JAFYZ666/hhCGKN5t9QFjbJQKUU/g8MNbFDbvfrgKXvI1QpZplPOnwIo99lX/AAmA==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/ansi-escapes": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.1.tgz", @@ -2446,19 +2643,6 @@ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", "dev": true }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/arch": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", @@ -2550,6 +2734,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/assertion-error": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", + "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + } + }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -2603,18 +2797,6 @@ "integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==", "dev": true }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/bottleneck": { "version": "2.19.5", "resolved": "https://registry.npmjs.org/bottleneck/-/bottleneck-2.19.5.tgz", @@ -2767,17 +2949,6 @@ "node": ">=8" } }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true - }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==" - }, "node_modules/bundle-require": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.1.0.tgz", @@ -2882,6 +3053,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/chai": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.3.3.tgz", + "integrity": "sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==", + "dev": true, + "license": "MIT", + "dependencies": { + "assertion-error": "^2.0.1", + "check-error": "^2.1.1", + "deep-eql": "^5.0.1", + "loupe": "^3.1.0", + "pathval": "^2.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -2922,43 +3110,14 @@ "node": ">=10" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/check-error": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, - "dependencies": { - "is-glob": "^4.0.1" - }, + "license": "MIT", "engines": { - "node": ">= 6" + "node": ">= 16" } }, "node_modules/clean-stack": { @@ -3557,16 +3716,14 @@ } } }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "node_modules/deep-eql": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", + "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", "dev": true, + "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=6" } }, "node_modules/deep-extend": { @@ -3627,15 +3784,6 @@ "node": ">=0.4.0" } }, - "node_modules/diff": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.0.0.tgz", - "integrity": "sha512-/VTCrvm5Z0JGty/BWHljh+BAiw3IK+2j87NGMu8Nwc/f48WoDAC395uomO9ZD117ZOBaHmkX1oyLvkVM/aIT3w==", - "dev": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", @@ -3713,14 +3861,6 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "dependencies": { - "safe-buffer": "^5.0.1" - } - }, "node_modules/emoji-regex": { "version": "10.4.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", @@ -3987,6 +4127,13 @@ "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==", + "dev": true, + "license": "MIT" + }, "node_modules/es-object-atoms": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", @@ -4290,6 +4437,16 @@ "node": ">=4.0" } }, + "node_modules/estree-walker": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", + "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0" + } + }, "node_modules/esutils": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", @@ -4328,6 +4485,16 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/expect-type": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.2.tgz", + "integrity": "sha512-JhFGDVJ7tmDJItKhYgJCGLOWjuK9vPxiXoUFLwLDc99NlmklilbiQJwoctZtt13+xMw91MCk/REan6MWHqDjyA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/fast-copy": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/fast-copy/-/fast-copy-3.0.2.tgz", @@ -4394,6 +4561,13 @@ "reusify": "^1.0.4" } }, + "node_modules/fflate": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz", + "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A==", + "dev": true, + "license": "MIT" + }, "node_modules/figures": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/figures/-/figures-6.1.0.tgz", @@ -4489,15 +4663,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "bin": { - "flat": "cli.js" - } - }, "node_modules/flat-cache": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", @@ -4513,10 +4678,11 @@ } }, "node_modules/flatted": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", - "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", - "dev": true + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz", + "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==", + "dev": true, + "license": "ISC" }, "node_modules/follow-redirects": { "version": "1.15.9", @@ -4793,50 +4959,18 @@ "through2": "~2.0.0" } }, - "node_modules/glob": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", - "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^5.0.1", - "once": "^1.3.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "dependencies": { - "is-glob": "^4.0.3" + "is-glob": "^4.0.3" }, "engines": { "node": ">=10.13.0" } }, - "node_modules/glob/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", @@ -5024,15 +5158,6 @@ "node": ">= 0.4" } }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "bin": { - "he": "bin/he" - } - }, "node_modules/highlight.js": { "version": "10.7.3", "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", @@ -5281,18 +5406,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/is-boolean-object": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", @@ -5465,15 +5578,6 @@ "node": ">=8" } }, - "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, - "engines": { - "node": ">=8" - } - }, "node_modules/is-port-reachable": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/is-port-reachable/-/is-port-reachable-4.0.0.tgz", @@ -5586,18 +5690,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", @@ -5675,6 +5767,15 @@ "node": ">= 0.6.0" } }, + "node_modules/jose": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.0.tgz", + "integrity": "sha512-TTQJyoEoKcC1lscpVDCSsVgYzUDg/0Bt3WE//WiTPK6uOCQC2KZS4MpugbMWt/zyjkopgZoXhZuCi00gLudfUA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/panva" + } + }, "node_modules/joycon": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/joycon/-/joycon-3.1.1.tgz", @@ -5782,52 +5883,12 @@ "node": "*" } }, - "node_modules/jsonwebtoken": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", - "integrity": "sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==", - "dependencies": { - "jws": "^3.2.2", - "lodash.includes": "^4.3.0", - "lodash.isboolean": "^3.0.3", - "lodash.isinteger": "^4.0.4", - "lodash.isnumber": "^3.0.3", - "lodash.isplainobject": "^4.0.6", - "lodash.isstring": "^4.0.1", - "lodash.once": "^4.0.0", - "ms": "^2.1.1", - "semver": "^7.5.4" - }, - "engines": { - "node": ">=12", - "npm": ">=6" - } - }, "node_modules/just-extend": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", "dev": true }, - "node_modules/jwa": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", - "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", - "dependencies": { - "buffer-equal-constant-time": "1.0.1", - "ecdsa-sig-formatter": "1.0.11", - "safe-buffer": "^5.0.1" - } - }, - "node_modules/jws": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", - "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", - "dependencies": { - "jwa": "^1.4.1", - "safe-buffer": "^5.0.1" - } - }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -5837,18 +5898,6 @@ "json-buffer": "3.0.1" } }, - "node_modules/ky": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/ky/-/ky-1.10.0.tgz", - "integrity": "sha512-YRPCzHEWZffbfvmRrfwa+5nwBHwZuYiTrfDX0wuhGBPV0pA/zCqcOq93MDssON/baIkpYbvehIX5aLpMxrRhaA==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sindresorhus/ky?sponsor=1" - } - }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -6175,35 +6224,17 @@ "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", "dev": true }, - "node_modules/lodash.includes": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", - "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==" - }, - "node_modules/lodash.isboolean": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", - "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==" - }, - "node_modules/lodash.isinteger": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", - "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==" - }, - "node_modules/lodash.isnumber": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", - "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==" - }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==" + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true }, "node_modules/lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", - "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==" + "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", + "dev": true }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -6211,11 +6242,6 @@ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", "dev": true }, - "node_modules/lodash.once": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==" - }, "node_modules/lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", @@ -6229,22 +6255,6 @@ "integrity": "sha512-e/zcLx6CSbmaEgFHCA7BnoQKyCtKMxnuWrJygbwPs/AIn+IMKl66L8/s+wBUn5LRw2pZx3bUHibiV1b6aTWIww==", "dev": true }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/log-update": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", @@ -6349,6 +6359,13 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/loupe": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.2.1.tgz", + "integrity": "sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==", + "dev": true, + "license": "MIT" + }, "node_modules/lru-cache": { "version": "10.4.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", @@ -6361,6 +6378,16 @@ "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", "dev": true }, + "node_modules/magic-string": { + "version": "0.30.19", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.19.tgz", + "integrity": "sha512-2N21sPY9Ws53PZvsEpVtNuSW+ScYbQdp4b9qUaL+9QkHUrGFKo56Lg9Emg5s9V/qrtNBmiR01sYhUOwu3H+VOw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, "node_modules/make-error": { "version": "1.3.6", "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", @@ -6549,72 +6576,14 @@ "node": ">=16 || 14 >=14.17" } }, - "node_modules/mocha": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-10.4.0.tgz", - "integrity": "sha512-eqhGB8JKapEYcC4ytX/xrzKforgEc3j1pGlAXVy3eRwrtAy5/nIfT1SvgGzfN0XZZxeLq0aQWkOUAmqIJiv+bA==", - "dev": true, - "dependencies": { - "ansi-colors": "4.1.1", - "browser-stdout": "1.3.1", - "chokidar": "3.5.3", - "debug": "4.3.4", - "diff": "5.0.0", - "escape-string-regexp": "4.0.0", - "find-up": "5.0.0", - "glob": "8.1.0", - "he": "1.2.0", - "js-yaml": "4.1.0", - "log-symbols": "4.1.0", - "minimatch": "5.0.1", - "ms": "2.1.3", - "serialize-javascript": "6.0.0", - "strip-json-comments": "3.1.1", - "supports-color": "8.1.1", - "workerpool": "6.2.1", - "yargs": "16.2.0", - "yargs-parser": "20.2.4", - "yargs-unparser": "2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": ">= 14.0.0" - } - }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.0.1.tgz", - "integrity": "sha512-nLDxIFRyhDblz3qMuq+SoRZED4+miJ/G+tdDrjkkkRnjAsBexeGpgjLEQ0blJy7rHhR2b93rhQY4SvyWu9v03g==", - "dev": true, - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/mocha/node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true - }, - "node_modules/mocha/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==", + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, + "license": "MIT", "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/ms": { @@ -6633,6 +6602,25 @@ "thenify-all": "^1.0.0" } }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6709,15 +6697,6 @@ "node": "^16.14.0 || >=18.0.0" } }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/npm": { "version": "10.8.0", "resolved": "https://registry.npmjs.org/npm/-/npm-10.8.0.tgz", @@ -9678,6 +9657,23 @@ "node": ">=8" } }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true, + "license": "MIT" + }, + "node_modules/pathval": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.1.tgz", + "integrity": "sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.16" + } + }, "node_modules/picocolors": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", @@ -9808,6 +9804,35 @@ "node": ">= 0.4" } }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/postcss-load-config": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", @@ -9974,15 +9999,6 @@ } ] }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, "node_modules/range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", @@ -10108,18 +10124,6 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, "node_modules/regexp.prototype.flags": { "version": "1.5.2", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", @@ -10308,13 +10312,13 @@ } }, "node_modules/rollup": { - "version": "4.29.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.29.1.tgz", - "integrity": "sha512-RaJ45M/kmJUzSWDs1Nnd5DdV4eerC98idtUOVr6FfKcgxqvjwHmxc5upLF9qZU9EpsVzzhleFahrT3shLuJzIw==", + "version": "4.52.3", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.52.3.tgz", + "integrity": "sha512-RIDh866U8agLgiIcdpB+COKnlCreHJLfIhWC3LVflku5YHfpnsIKigRZeFfMfCc4dVcqNVfQQ5gO/afOck064A==", "dev": true, "license": "MIT", "dependencies": { - "@types/estree": "1.0.6" + "@types/estree": "1.0.8" }, "bin": { "rollup": "dist/bin/rollup" @@ -10324,25 +10328,28 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.29.1", - "@rollup/rollup-android-arm64": "4.29.1", - "@rollup/rollup-darwin-arm64": "4.29.1", - "@rollup/rollup-darwin-x64": "4.29.1", - "@rollup/rollup-freebsd-arm64": "4.29.1", - "@rollup/rollup-freebsd-x64": "4.29.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.29.1", - "@rollup/rollup-linux-arm-musleabihf": "4.29.1", - "@rollup/rollup-linux-arm64-gnu": "4.29.1", - "@rollup/rollup-linux-arm64-musl": "4.29.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.29.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.29.1", - "@rollup/rollup-linux-riscv64-gnu": "4.29.1", - "@rollup/rollup-linux-s390x-gnu": "4.29.1", - "@rollup/rollup-linux-x64-gnu": "4.29.1", - "@rollup/rollup-linux-x64-musl": "4.29.1", - "@rollup/rollup-win32-arm64-msvc": "4.29.1", - "@rollup/rollup-win32-ia32-msvc": "4.29.1", - "@rollup/rollup-win32-x64-msvc": "4.29.1", + "@rollup/rollup-android-arm-eabi": "4.52.3", + "@rollup/rollup-android-arm64": "4.52.3", + "@rollup/rollup-darwin-arm64": "4.52.3", + "@rollup/rollup-darwin-x64": "4.52.3", + "@rollup/rollup-freebsd-arm64": "4.52.3", + "@rollup/rollup-freebsd-x64": "4.52.3", + "@rollup/rollup-linux-arm-gnueabihf": "4.52.3", + "@rollup/rollup-linux-arm-musleabihf": "4.52.3", + "@rollup/rollup-linux-arm64-gnu": "4.52.3", + "@rollup/rollup-linux-arm64-musl": "4.52.3", + "@rollup/rollup-linux-loong64-gnu": "4.52.3", + "@rollup/rollup-linux-ppc64-gnu": "4.52.3", + "@rollup/rollup-linux-riscv64-gnu": "4.52.3", + "@rollup/rollup-linux-riscv64-musl": "4.52.3", + "@rollup/rollup-linux-s390x-gnu": "4.52.3", + "@rollup/rollup-linux-x64-gnu": "4.52.3", + "@rollup/rollup-linux-x64-musl": "4.52.3", + "@rollup/rollup-openharmony-arm64": "4.52.3", + "@rollup/rollup-win32-arm64-msvc": "4.52.3", + "@rollup/rollup-win32-ia32-msvc": "4.52.3", + "@rollup/rollup-win32-x64-gnu": "4.52.3", + "@rollup/rollup-win32-x64-msvc": "4.52.3", "fsevents": "~2.3.2" } }, @@ -10402,6 +10409,7 @@ "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, "funding": [ { "type": "github", @@ -10791,6 +10799,7 @@ "version": "7.6.2", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, "bin": { "semver": "bin/semver.js" }, @@ -10825,15 +10834,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/serialize-javascript": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.0.tgz", - "integrity": "sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag==", - "dev": true, - "dependencies": { - "randombytes": "^2.1.0" - } - }, "node_modules/serve": { "version": "14.2.4", "resolved": "https://registry.npmjs.org/serve/-/serve-14.2.4.tgz", @@ -11088,6 +11088,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/siginfo": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", + "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", + "dev": true, + "license": "ISC" + }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", @@ -11218,6 +11225,21 @@ "node": ">=0.3.1" } }, + "node_modules/sirv": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, "node_modules/skin-tone": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/skin-tone/-/skin-tone-2.0.0.tgz", @@ -11276,6 +11298,16 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/spawn-error-forwarder": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/spawn-error-forwarder/-/spawn-error-forwarder-1.0.0.tgz", @@ -11323,6 +11355,20 @@ "node": ">= 10.x" } }, + "node_modules/stackback": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", + "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", + "dev": true, + "license": "MIT" + }, + "node_modules/std-env": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.9.0.tgz", + "integrity": "sha512-UGvjygr6F6tpH7o2qyqR6QYpwraIjKSdtzyBdyytFOHmPZY917kwdwLG0RbOjWOnKmnm3PeHjaoLLMie7kPLQw==", + "dev": true, + "license": "MIT" + }, "node_modules/stream-combiner2": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", @@ -11539,6 +11585,26 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/strip-literal": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-literal/-/strip-literal-3.0.0.tgz", + "integrity": "sha512-TcccoMhJOM3OebGhSBEmp3UZ2SfDMZUEBdRA/9ynfLi8yYajyWX3JiXArcJt4Umh4vISpspkQIY8ZZoCqjbviA==", + "dev": true, + "license": "MIT", + "dependencies": { + "js-tokens": "^9.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/strip-literal/node_modules/js-tokens": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-9.0.1.tgz", + "integrity": "sha512-mxa9E9ITFOt0ban3j6L5MpjwegGz6lBQmM1IJkWeBZGcMxto50+eWdjC/52xDbS2vy0k7vIMK0Fe2wfL9OQSpQ==", + "dev": true, + "license": "MIT" + }, "node_modules/sucrase": { "version": "3.35.0", "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", @@ -11771,33 +11837,46 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/tinybench": { + "version": "2.9.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", + "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", + "dev": true, + "license": "MIT" + }, "node_modules/tinyexec": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", - "integrity": "sha512-WiCJLEECkO18gwqIp6+hJg0//p23HXp4S+gGtAKu3mI2F2/sXC4FvHvXvB0zJVVaTPhx1/tOwdbRsa1sOBIKqQ==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", "dev": true, "license": "MIT" }, "node_modules/tinyglobby": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.10.tgz", - "integrity": "sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==", + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", "dev": true, "license": "MIT", "dependencies": { - "fdir": "^6.4.2", - "picomatch": "^4.0.2" + "fdir": "^6.5.0", + "picomatch": "^4.0.3" }, "engines": { "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" } }, "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.4.2", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.2.tgz", - "integrity": "sha512-KnhMXsKSPZlAhp7+IjUkRZKPb4fUyccpDrdFXbi4QL1qkmFh9kVY09Yox+n4MaOb3lHZ1Tv829C3oaaXoMYPDQ==", + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", "dev": true, "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, "peerDependencies": { "picomatch": "^3 || ^4" }, @@ -11808,9 +11887,9 @@ } }, "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", "engines": { @@ -11820,6 +11899,36 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/tinypool": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.1.1.tgz", + "integrity": "sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.0.0 || >=20.0.0" + } + }, + "node_modules/tinyrainbow": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", + "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tinyspy": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-4.0.4.tgz", + "integrity": "sha512-azl+t0z7pw/z958Gy9svOTuzqIk6xq+NSheJzn5MMWtWTFywIacg2wUlzKFGtt3cthx0r2SxMK0yzJOR0IES7Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.0.0" + } + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -11832,6 +11941,16 @@ "node": ">=8.0" } }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/tr46": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", @@ -12402,199 +12521,942 @@ "node": ">= 0.8" } }, - "node_modules/vscode-oniguruma": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", - "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", - "dev": true - }, - "node_modules/vscode-textmate": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", - "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", - "dev": true - }, - "node_modules/webidl-conversions": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", - "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/whatwg-url": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", - "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "node_modules/vite": { + "version": "6.3.6", + "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.6.tgz", + "integrity": "sha512-0msEVHJEScQbhkbVTb/4iHZdJ6SXp/AvxL2sjwYQFfBqleHtnCqv1J3sa9zbWz/6kW1m9Tfzn92vW+kZ1WV6QA==", "dev": true, "license": "MIT", "dependencies": { - "lodash.sortby": "^4.7.0", - "tr46": "^1.0.1", - "webidl-conversions": "^4.0.2" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "dependencies": { - "isexe": "^2.0.0" + "esbuild": "^0.25.0", + "fdir": "^6.4.4", + "picomatch": "^4.0.2", + "postcss": "^8.5.3", + "rollup": "^4.34.9", + "tinyglobby": "^0.2.13" }, "bin": { - "node-which": "bin/node-which" + "vite": "bin/vite.js" }, "engines": { - "node": ">= 8" - } - }, - "node_modules/which-boxed-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", - "dev": true, - "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "jiti": ">=1.21.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "sass-embedded": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } } }, - "node_modules/which-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", - "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "node_modules/vite-node": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.2.4.tgz", + "integrity": "sha512-EbKSKh+bh1E1IFxeO0pg1n4dvoOTt0UDiXMd/qn++r98+jPO1xtJilvXldeuQ8giIB5IkpjCgMleHMNEsGH6pg==", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.7", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.2" + "cac": "^6.7.14", + "debug": "^4.4.1", + "es-module-lexer": "^1.7.0", + "pathe": "^2.0.3", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0" + }, + "bin": { + "vite-node": "vite-node.mjs" }, "engines": { - "node": ">= 0.4" + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://opencollective.com/vitest" } }, - "node_modules/widest-line": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", - "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "node_modules/vite-node/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, + "license": "MIT", "dependencies": { - "string-width": "^5.0.1" + "ms": "^2.1.3" }, "engines": { - "node": ">=12" + "node": ">=6.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/widest-line/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "node_modules/vite-node/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/widest-line/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true + "license": "MIT" }, - "node_modules/widest-line/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "node_modules/vite/node_modules/@esbuild/aix-ppc64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", + "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=18" } }, - "node_modules/widest-line/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "node_modules/vite/node_modules/@esbuild/android-arm": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", + "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", + "cpu": [ + "arm" + ], "dev": true, - "dependencies": { - "ansi-regex": "^6.0.1" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" + "node": ">=18" } }, - "node_modules/word-wrap": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", - "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "node_modules/vite/node_modules/@esbuild/android-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", + "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", + "cpu": [ + "arm64" + ], "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=0.10.0" + "node": ">=18" } }, - "node_modules/wordwrap": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", - "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", - "dev": true - }, - "node_modules/workerpool": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.2.1.tgz", - "integrity": "sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw==", - "dev": true - }, - "node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "node_modules/vite/node_modules/@esbuild/android-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", + "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", + "cpu": [ + "x64" + ], "dev": true, - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], "engines": { "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "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==", + "node_modules/vite/node_modules/@esbuild/darwin-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", + "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/darwin-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", + "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", + "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/freebsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", + "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", + "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", + "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ia32": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", + "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-loong64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", + "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-mips64el": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", + "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-ppc64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", + "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-riscv64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", + "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-s390x": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", + "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/linux-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", + "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", + "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/netbsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", + "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", + "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/openbsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", + "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/sunos-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", + "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", + "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-ia32": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", + "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/@esbuild/win32-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", + "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/vite/node_modules/esbuild": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.10.tgz", + "integrity": "sha512-9RiGKvCwaqxO2owP61uQ4BgNborAQskMR6QusfWzQqv7AZOg5oGehdY2pRJMTKuwxd1IDBP4rSbI5lHzU7SMsQ==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.25.10", + "@esbuild/android-arm": "0.25.10", + "@esbuild/android-arm64": "0.25.10", + "@esbuild/android-x64": "0.25.10", + "@esbuild/darwin-arm64": "0.25.10", + "@esbuild/darwin-x64": "0.25.10", + "@esbuild/freebsd-arm64": "0.25.10", + "@esbuild/freebsd-x64": "0.25.10", + "@esbuild/linux-arm": "0.25.10", + "@esbuild/linux-arm64": "0.25.10", + "@esbuild/linux-ia32": "0.25.10", + "@esbuild/linux-loong64": "0.25.10", + "@esbuild/linux-mips64el": "0.25.10", + "@esbuild/linux-ppc64": "0.25.10", + "@esbuild/linux-riscv64": "0.25.10", + "@esbuild/linux-s390x": "0.25.10", + "@esbuild/linux-x64": "0.25.10", + "@esbuild/netbsd-arm64": "0.25.10", + "@esbuild/netbsd-x64": "0.25.10", + "@esbuild/openbsd-arm64": "0.25.10", + "@esbuild/openbsd-x64": "0.25.10", + "@esbuild/openharmony-arm64": "0.25.10", + "@esbuild/sunos-x64": "0.25.10", + "@esbuild/win32-arm64": "0.25.10", + "@esbuild/win32-ia32": "0.25.10", + "@esbuild/win32-x64": "0.25.10" + } + }, + "node_modules/vite/node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/vite/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vitest": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.2.4.tgz", + "integrity": "sha512-LUCP5ev3GURDysTWiP47wRRUpLKMOfPh+yKTx3kVIEiu5KOMeqzpnYNsKyOoVrULivR8tLcks4+lga33Whn90A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/chai": "^5.2.2", + "@vitest/expect": "3.2.4", + "@vitest/mocker": "3.2.4", + "@vitest/pretty-format": "^3.2.4", + "@vitest/runner": "3.2.4", + "@vitest/snapshot": "3.2.4", + "@vitest/spy": "3.2.4", + "@vitest/utils": "3.2.4", + "chai": "^5.2.0", + "debug": "^4.4.1", + "expect-type": "^1.2.1", + "magic-string": "^0.30.17", + "pathe": "^2.0.3", + "picomatch": "^4.0.2", + "std-env": "^3.9.0", + "tinybench": "^2.9.0", + "tinyexec": "^0.3.2", + "tinyglobby": "^0.2.14", + "tinypool": "^1.1.1", + "tinyrainbow": "^2.0.0", + "vite": "^5.0.0 || ^6.0.0 || ^7.0.0-0", + "vite-node": "3.2.4", + "why-is-node-running": "^2.3.0" + }, + "bin": { + "vitest": "vitest.mjs" + }, + "engines": { + "node": "^18.0.0 || ^20.0.0 || >=22.0.0" + }, + "funding": { + "url": "https://opencollective.com/vitest" + }, + "peerDependencies": { + "@edge-runtime/vm": "*", + "@types/debug": "^4.1.12", + "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", + "@vitest/browser": "3.2.4", + "@vitest/ui": "3.2.4", + "happy-dom": "*", + "jsdom": "*" + }, + "peerDependenciesMeta": { + "@edge-runtime/vm": { + "optional": true + }, + "@types/debug": { + "optional": true + }, + "@types/node": { + "optional": true + }, + "@vitest/browser": { + "optional": true + }, + "@vitest/ui": { + "optional": true + }, + "happy-dom": { + "optional": true + }, + "jsdom": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/vitest/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/vitest/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true + }, + "node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/why-is-node-running": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", + "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", + "dev": true, + "license": "MIT", + "dependencies": { + "siginfo": "^2.0.0", + "stackback": "0.0.2" + }, + "bin": { + "why-is-node-running": "cli.js" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/widest-line": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-4.0.1.tgz", + "integrity": "sha512-o0cyEG0e8GPzT4iGHphIOh0cJOV8fivsXxddQasHPHfoZf1ZexrfeA21w2NaEN1RHE+fXlfISmOE8R9N3u3Qig==", + "dev": true, + "dependencies": { + "string-width": "^5.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/widest-line/node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/widest-line/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, + "node_modules/widest-line/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/widest-line/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.2.1", + "string-width": "^7.0.0", + "strip-ansi": "^7.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "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" }, @@ -12739,33 +13601,6 @@ "node": ">=10" } }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs-unparser/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/yargs/node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", diff --git a/package.json b/package.json index bd8c30e7..e449107d 100644 --- a/package.json +++ b/package.json @@ -38,8 +38,8 @@ "lint": "eslint --ext .ts ./src", "lint:fix": "npm run lint -- --fix", "pretest": "echo ' 🔑 Creating valid keypair for testing' && sh test/make-private-keys.sh &> /dev/null", - "test:unit": "mocha -r dotenv/config -r ts-node/register ./src/**/*.spec.ts", - "test:integration": "mocha -r dotenv/config -r ts-node/register --timeout 10000 ./test/**/*.test.ts", + "test:unit": "vitest run src", + "test:integration": "vitest run test", "test": "npm run test:unit && npm run test:integration", "build": "rm -rf lib && tsup", "postbuild": "cp ./lib/index.d.ts ./lib/index.d.cts", @@ -55,20 +55,18 @@ "@types/debug": "^4.1.5", "contentful-management": "^11.6.1", "debug": "^4.2.0", - "jsonwebtoken": "^9.0.0", - "ky": "^1.10.0", + "jose": "^6.1.0", "lru-cache": "^10.4.3", "runtypes": "^5.0.1" }, "devDependencies": { "@semantic-release/changelog": "6.0.3", "@semantic-release/git": "10.0.1", - "@types/jsonwebtoken": "9.0.6", - "@types/mocha": "10.0.6", "@types/node": "^22.18.6", "@types/sinon": "17.0.3", "@typescript-eslint/eslint-plugin": "7.10.0", "@typescript-eslint/parser": "7.10.0", + "@vitest/ui": "^3.2.4", "base64url": "3.0.1", "dotenv": "16.4.5", "eslint": "8.57.0", @@ -76,7 +74,6 @@ "eslint-plugin-prettier": "^5.0.0", "husky": "9.0.11", "lint-staged": "15.2.10", - "mocha": "10.4.0", "prettier": "3.2.5", "semantic-release": "23.1.1", "serve": "14.2.4", @@ -84,7 +81,8 @@ "ts-node": "10.9.2", "tsup": "^8.3.5", "typedoc": "0.25.13", - "typescript": "5.4.5" + "typescript": "5.4.5", + "vitest": "^3.2.4" }, "lint-staged": { "*.ts": [ diff --git a/src/keys/get-management-token.spec.ts b/src/keys/get-management-token.spec.ts index cab1eded..58cc9857 100644 --- a/src/keys/get-management-token.spec.ts +++ b/src/keys/get-management-token.spec.ts @@ -1,4 +1,4 @@ -import * as assert from 'assert' +import { describe, it, expect, beforeEach, afterEach } from 'vitest' import * as fs from 'fs' import * as path from 'path' @@ -11,7 +11,7 @@ import { } from './get-management-token' import { HttpError } from '../utils' import { Logger } from '../utils' -import { sign } from 'jsonwebtoken' +import { SignJWT } from 'jose' import { LRUCache } from 'lru-cache' const PRIVATE_KEY = fs.readFileSync(path.join(__dirname, '..', '..', 'keys', 'key.pem'), 'utf-8') @@ -50,22 +50,23 @@ describe('getManagementToken', () => { const result = await getManagementToken(PRIVATE_KEY, DEFAULT_OPTIONS) - assert.deepStrictEqual(result, mockToken) - assert(fetchStub.calledOnce) + expect(result).toEqual(mockToken) + expect(fetchStub.calledOnce).toBe(true) console.log(fetchStub.args) - assert( + expect( fetchStub.calledWith( `/spaces/${SPACE_ID}/environments/${ENVIRONMENT_ID}/app_installations/${APP_ID}/access_tokens`, sinon.match({ method: 'POST', headers: { Authorization: sinon.match.string } }), ), - ) + ).toBe(true) }) it('caches token while valid', async () => { const logger = noop as unknown as Logger - const mockToken = sign({ a: 'b' }, 'a-secret-key', { - expiresIn: '10 minutes', - }) + const mockToken = await new SignJWT({ a: 'b' }) + .setProtectedHeader({ alg: 'HS256' }) + .setExpirationTime('10 minutes') + .sign(new TextEncoder().encode('a-secret-key')) fetchStub.resolves({ ok: true, status: 201, json: () => Promise.resolve({ token: mockToken }) }) const getManagementToken = createGetManagementToken( @@ -76,18 +77,19 @@ describe('getManagementToken', () => { const optionsWithCaching = { ...DEFAULT_OPTIONS, reuseToken: true } const result = await getManagementToken(PRIVATE_KEY, optionsWithCaching) - assert.strictEqual(result, mockToken) + expect(result).toEqual(mockToken) const secondResult = await getManagementToken(PRIVATE_KEY, optionsWithCaching) - assert.strictEqual(secondResult, mockToken) + expect(secondResult).toEqual(mockToken) - assert(fetchStub.calledOnce) + expect(fetchStub.calledOnce).toBe(true) }) it('does not cache expired token', async () => { const logger = noop as unknown as Logger - const mockToken = sign({ a: 'b' }, 'a-secret-key', { - expiresIn: '5 minutes', - }) + const mockToken = await new SignJWT({ a: 'b' }) + .setProtectedHeader({ alg: 'HS256' }) + .setExpirationTime('5 minutes') + .sign(new TextEncoder().encode('a-secret-key')) fetchStub.resolves({ ok: true, status: 201, json: () => Promise.resolve({ token: mockToken }) }) const cache: LRUCache = new LRUCache({ max: 10 }) @@ -99,7 +101,7 @@ describe('getManagementToken', () => { const optionsWithCaching = { ...DEFAULT_OPTIONS, reuseToken: true } const result = await getManagementToken(PRIVATE_KEY, optionsWithCaching) - assert.strictEqual(result, mockToken) + expect(result).toEqual(mockToken) // Overwrite TTL expiry to 5ms const cacheKey = APP_ID + SPACE_ID + ENVIRONMENT_ID + PRIVATE_KEY.slice(32, 132) @@ -111,8 +113,8 @@ describe('getManagementToken', () => { }) const secondResult = await getManagementToken(PRIVATE_KEY, optionsWithCaching) - assert.strictEqual(secondResult, mockToken) - assert(fetchStub.calledTwice) + expect(secondResult).toEqual(mockToken) + expect(fetchStub.calledTwice).toBe(true) }) describe('when using a keyId', () => { @@ -132,27 +134,27 @@ describe('getManagementToken', () => { const result = await getManagementToken(PRIVATE_KEY, { ...DEFAULT_OPTIONS, keyId: 'keyId' }) - assert.deepStrictEqual(result, mockToken) - assert( + expect(result).toEqual(mockToken) + expect( fetchStub.calledWith( `/spaces/${SPACE_ID}/environments/${ENVIRONMENT_ID}/app_installations/${APP_ID}/access_tokens`, sinon.match({ method: 'POST', headers: { Authorization: sinon.match.string } }), ), - ) + ).toBe(true) }) }) describe('when private key is incorrect', () => { it('throws if missing', async () => { - await assert.rejects(async () => { + await expect(async () => { // @ts-ignore Testing javascript code await getManagementToken(undefined, DEFAULT_OPTIONS) - }) + }).rejects.toThrow() }) it('throws if generated with wrong algorithm', async () => { - await assert.rejects(async () => { + await expect(async () => { await getManagementToken('not_a_private_key', DEFAULT_OPTIONS) - }) + }).rejects.toThrow() }) }) @@ -166,9 +168,9 @@ describe('getManagementToken', () => { defaultCache, ) - await assert.rejects(async () => { + await expect(async () => { await getManagementToken(PRIVATE_KEY, DEFAULT_OPTIONS) - }, HttpError) + }).rejects.toThrow(HttpError) }) }) }) diff --git a/src/keys/get-management-token.ts b/src/keys/get-management-token.ts index 27fe3bf5..37355c0c 100644 --- a/src/keys/get-management-token.ts +++ b/src/keys/get-management-token.ts @@ -1,11 +1,7 @@ -import * as jwtImpl from 'jsonwebtoken' -import type { SignOptions } from 'jsonwebtoken' +import { createPrivateKey } from 'node:crypto' import { LRUCache } from 'lru-cache' import { createLogger, createValidateStatusCode, Logger } from '../utils' import { FetchOptions, makeRequest, withDefaultOptions, withHook, withRetry } from '../utils/http' - -const jwt = 'default' in jwtImpl ? jwtImpl.default : jwtImpl -const { sign, decode } = jwt as typeof jwtImpl export interface GetManagementTokenOptions { appInstallationId: string spaceId: string @@ -21,17 +17,24 @@ let defaultCache: LRUCache | undefined * Synchronously sign the given privateKey into a JSON Web Token string * @internal */ -const generateOneTimeToken = ( - privateKey: string, +const generateOneTimeToken = async ( + privateKeyPem: string, { appId, keyId }: { appId: string; keyId?: string }, { log }: { log: Logger }, -): string => { +): Promise => { log('Signing a JWT token with private key') try { - const baseSignOptions: SignOptions = { algorithm: 'RS256', issuer: appId, expiresIn: '10m' } - const signOptions: SignOptions = keyId ? { ...baseSignOptions, keyid: keyId } : baseSignOptions - - const token = sign({}, privateKey, signOptions) + const { SignJWT, importPKCS8 } = await import('jose') + const privateKey = privateKeyPem.includes('BEGIN PRIVATE KEY') + ? await importPKCS8(privateKeyPem, 'RS256') + : await Promise.resolve(createPrivateKey(privateKeyPem)) // "BEGIN RSA PRIVATE KEY" (PKCS#1) + const secureHeaders = keyId ? { kid: keyId, alg: 'RS256' } : { alg: 'RS256' } + const signer = new SignJWT({}) + .setProtectedHeader(secureHeaders) + .setIssuedAt() + .setIssuer(appId) + .setExpirationTime('10m') + const token = await signer.sign(privateKey) log('Successfully signed token') return token } catch (e) { @@ -84,6 +87,7 @@ export const createGetManagementToken = ( cache: LRUCache, ) => { return async (privateKey: unknown, opts: GetManagementTokenOptions): Promise => { + const { decodeJwt } = await import('jose') if (!(typeof privateKey === 'string')) { throw new ReferenceError('Invalid privateKey: expected a string representing a private key') } @@ -100,15 +104,15 @@ export const createGetManagementToken = ( return existing as string } } - - const appToken = generateOneTimeToken( + console.log('gettingOneTimeToken') + const appToken = await generateOneTimeToken( privateKey, { appId: opts.appInstallationId, keyId: opts.keyId }, { log }, ) const ott = await getTokenFromOneTimeToken(appToken, opts, { log, fetchOptions }) if (opts.reuseToken) { - const decoded = decode(ott) + const decoded = decodeJwt(ott) if (decoded && typeof decoded === 'object' && decoded.exp) { // Internally expire cached tokens a bit earlier to make sure token isn't expired on arrival const safetyMargin = 10 @@ -150,6 +154,7 @@ export const getManagementToken = async (privateKey: string, opts: GetManagement } const httpClientOpts = typeof opts.host !== 'undefined' ? { prefixUrl: opts.host } : {} + console.log('createGetManagementToken') return createGetManagementToken( createLogger({ namespace: 'get-management-token' }), withDefaultOptions(httpClientOpts), diff --git a/src/requests/verify-request.spec.ts b/src/requests/verify-request.spec.ts index 56c50dad..d5bd935e 100644 --- a/src/requests/verify-request.spec.ts +++ b/src/requests/verify-request.spec.ts @@ -1,4 +1,4 @@ -import * as assert from 'assert' +import { describe, it, expect } from 'vitest' import { verifyRequest } from './verify-request' import { @@ -69,7 +69,7 @@ describe('verifyRequest', () => { now, ) - assert(verifyRequest(VALID_SECRET, incomingRequest, 0)) + expect(verifyRequest(VALID_SECRET, incomingRequest, 0)).toBe(true) }) it('verifies a verified request with subject-id', () => { @@ -84,7 +84,7 @@ describe('verifyRequest', () => { now, ) - assert(verifyRequest(VALID_SECRET, incomingRequest, 0)) + expect(verifyRequest(VALID_SECRET, incomingRequest, 0)).toBe(true) }) describe('with time to live', () => { @@ -100,8 +100,7 @@ describe('verifyRequest', () => { oneMinuteAgo, ) - assert.throws( - () => verifyRequest(VALID_SECRET, incomingRequest, 1), + expect(() => verifyRequest(VALID_SECRET, incomingRequest, 1)).toThrow( ExpiredRequestException, ) }) @@ -118,8 +117,7 @@ describe('verifyRequest', () => { oneMinuteAgo, ) - assert.doesNotThrow( - () => verifyRequest(VALID_SECRET, incomingRequest, 0), + expect(() => verifyRequest(VALID_SECRET, incomingRequest, 0)).not.toThrow( ExpiredRequestException, ) }) @@ -160,7 +158,7 @@ describe('verifyRequest', () => { delete incomingRequest.headers[ContentfulContextHeader.AppId] } - assert(verifyRequest(VALID_SECRET, incomingRequest)) + expect(verifyRequest(VALID_SECRET, incomingRequest)).toBe(true) }) it('verifies correctly with keys with whitespace', () => { const incomingRequest = makeIncomingRequest({}, makeContextHeaders(contextHeaders)) @@ -196,21 +194,21 @@ describe('verifyRequest', () => { delete incomingRequest.headers[ContentfulContextHeader.AppId] } - assert(verifyRequest(VALID_SECRET, incomingRequest)) + expect(verifyRequest(VALID_SECRET, incomingRequest)).toBe(true) }) it('throws when missing signature', () => { const incomingRequest = makeIncomingRequest({}, makeContextHeaders(contextHeaders)) delete incomingRequest.headers[ContentfulHeader.Signature] - assert.throws(() => verifyRequest(VALID_SECRET, incomingRequest)) + expect(() => verifyRequest(VALID_SECRET, incomingRequest)).toThrow() }) it('throws when missing timestamp', () => { const incomingRequest = makeIncomingRequest({}, makeContextHeaders(contextHeaders)) delete incomingRequest.headers[ContentfulHeader.Timestamp] - assert.throws(() => verifyRequest(VALID_SECRET, incomingRequest)) + expect(() => verifyRequest(VALID_SECRET, incomingRequest)).toThrow() }) it('throws when missing signed headers', () => { const incomingRequest = makeIncomingRequest( @@ -222,7 +220,7 @@ describe('verifyRequest', () => { delete incomingRequest.headers[ContentfulHeader.SignedHeaders] - assert.throws(() => verifyRequest(VALID_SECRET, incomingRequest)) + expect(() => verifyRequest(VALID_SECRET, incomingRequest)).toThrow() }) }) @@ -252,7 +250,7 @@ describe('verifyRequest', () => { delete incomingRequest.headers['Authorization'] delete incomingRequest.headers['Cache-Control'] - assert(verifyRequest(VALID_SECRET, incomingRequest)) + expect(verifyRequest(VALID_SECRET, incomingRequest)).toBe(true) }) it('verifies with keys with whitespace', () => { const authorization = 'Bearer TOKEN' @@ -279,7 +277,7 @@ describe('verifyRequest', () => { delete incomingRequest.headers['Authorization'] delete incomingRequest.headers['Cache-Control'] - assert(verifyRequest(VALID_SECRET, incomingRequest)) + expect(verifyRequest(VALID_SECRET, incomingRequest)).toBe(true) }) it('verifies with different headers, if they are not signed', () => { const authorization = 'Bearer TOKEN' @@ -297,7 +295,7 @@ describe('verifyRequest', () => { incomingRequest.headers['Content-Type'] = 'application/json' - assert(verifyRequest(VALID_SECRET, incomingRequest)) + expect(verifyRequest(VALID_SECRET, incomingRequest)).toBe(true) }) it('does not verify with different signed headers', () => { const authorization = 'Bearer TOKEN' @@ -315,7 +313,7 @@ describe('verifyRequest', () => { incomingRequest.headers['Authorization'] = 'something else' - assert(!verifyRequest(VALID_SECRET, incomingRequest)) + expect(verifyRequest(VALID_SECRET, incomingRequest)).toBe(false) }) it("verifies with headers sorted lower than contentful's", () => { @@ -329,7 +327,7 @@ describe('verifyRequest', () => { makeContextHeaders(contextHeaders), ) - assert(verifyRequest(VALID_SECRET, incomingRequest)) + expect(verifyRequest(VALID_SECRET, incomingRequest)).toBe(true) }) }) @@ -346,7 +344,7 @@ describe('verifyRequest', () => { incomingRequest.path = pathWithQueryTwo - assert(!verifyRequest(VALID_SECRET, incomingRequest)) + expect(verifyRequest(VALID_SECRET, incomingRequest)).toBe(false) }) }) @@ -359,7 +357,7 @@ describe('verifyRequest', () => { incomingRequest.method = 'POST' - assert(!verifyRequest(VALID_SECRET, incomingRequest)) + expect(verifyRequest(VALID_SECRET, incomingRequest)).toBe(false) }) }) @@ -375,7 +373,7 @@ describe('verifyRequest', () => { ) const differentSecret = `q${VALID_SECRET.slice(1, VALID_SECRET.length)}` - assert(!verifyRequest(differentSecret, incomingRequest)) + expect(verifyRequest(differentSecret, incomingRequest)).toBe(false) }) }) }) diff --git a/test/integration/keys.test.ts b/test/integration/keys.test.ts index 3e5f1dbd..3e2e9d6c 100644 --- a/test/integration/keys.test.ts +++ b/test/integration/keys.test.ts @@ -1,6 +1,6 @@ import * as fs from 'fs' import * as path from 'path' -import * as assert from 'assert' +import { describe, it, beforeAll, expect } from 'vitest' //TODO use built version import { getManagementToken } from '../../src/keys' @@ -8,7 +8,7 @@ import { cleanOldKeys, setPublicKey } from '../utils' import { config, makeRequest } from '../../src/utils/http' describe('Keys Utilities', () => { - before(async () => { + beforeAll(async () => { await cleanOldKeys() const pubKey = fs.readFileSync(path.join(__dirname, '..', '..', 'keys', 'key.der.pub')) @@ -32,7 +32,7 @@ describe('Keys Utilities', () => { environmentId, }) - await assert.doesNotReject(() => { + await expect(async () => { const requestor = makeRequest( `/spaces/${spaceId}/entries`, { @@ -45,6 +45,6 @@ describe('Keys Utilities', () => { ) return requestor() - }) + }).not.toThrow() }) }) diff --git a/tsconfig.eslint.json b/tsconfig.eslint.json index f25ce8c3..7bb4de04 100644 --- a/tsconfig.eslint.json +++ b/tsconfig.eslint.json @@ -1,6 +1,6 @@ { "extends": "./tsconfig.json", - "include": ["./src/**/*", "./src/**/*.spec.ts", "./test/**/*.test.ts"], + "include": ["./src/**/*", "./src/**/*.spec.ts", "./test/**/*.test.ts", "./vitest.setup.ts", "./vitest.config.ts"], "exclude": [], "compilerOptions": { "lib": ["es2020", "esnext", "dom"] diff --git a/tsup.config.js b/tsup.config.js index 793c2bf9..614e8a87 100644 --- a/tsup.config.js +++ b/tsup.config.js @@ -1,15 +1,28 @@ import { defineConfig } from 'tsup' -export default defineConfig({ +const allJsConfig = { entry: ['src/index.ts','src/keys/index.ts','src/requests/index.ts','src/requests/typings/index.ts','src/utils/index.ts'], outDir: 'lib', - format: ['cjs', 'esm'], - dts: true, - clean: true, - splitting: false, - sourcemap: true, target: 'node18', - shims: true, + dts: true, + external: ['jose'], preserveModules: true, + sourcemap: true, outExtension: ({ format }) => (format === 'esm' ? { js: '.mjs' } : { js: '.cjs' }), -}) + +} +export default defineConfig([ + { + ...allJsConfig, + format: ['esm'], + clean: true, + splitting: true, + shims: true, + }, + { + ...allJsConfig, + format: ['cjs'], + clean: false, + splitting: false, + } +]) diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 00000000..4f4b75ca --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,11 @@ +import { defineConfig } from 'vitest/config' + +export default defineConfig({ + test: { + globals: true, + environment: 'node', + include: ['src/**/*.spec.ts', 'test/**/*.test.ts'], + setupFiles: ['dotenv/config', './vitest.setup.ts'], + timeout: 10000, + }, +}) diff --git a/vitest.setup.ts b/vitest.setup.ts new file mode 100644 index 00000000..4c6280cd --- /dev/null +++ b/vitest.setup.ts @@ -0,0 +1,7 @@ +import { webcrypto } from 'node:crypto' + +// Polyfill crypto for jose library +if (!globalThis.crypto) { + // @ts-ignore + globalThis.crypto = webcrypto +}