diff --git a/CHANGELOG.md b/CHANGELOG.md index f42e98a..ef49f55 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +## [1.4.0-stage.1](https://github.com/aziontech/lib/compare/v1.3.0...v1.4.0-stage.1) (2024-07-25) + + +### Features + +* create jwt package (#11) ([b78f30e](https://github.com/aziontech/lib/commit/b78f30eb8def541f0b829bd9f06afacac72a0ab5)) + ## [1.3.0](https://github.com/aziontech/lib/compare/v1.2.0...v1.3.0) (2024-07-18) diff --git a/package-lock.json b/package-lock.json index 32e55c4..059ab23 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "azion", - "version": "1.2.0-stage.1", + "version": "1.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "azion", - "version": "1.2.0-stage.1", + "version": "1.3.0", "license": "MIT", "workspaces": [ "packages/*" @@ -32,10 +32,7 @@ "typescript-eslint": "^7.16.0" }, "engines": { - "node": ">=18.0.0", - "npm": ">=10.2.3", - "pnpm": "please-use-npm", - "yarn": "please-use-npm" + "node": ">=18.0.0" } }, "node_modules/@ampproject/remapping": { @@ -65,30 +62,30 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", - "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.9.tgz", + "integrity": "sha512-e701mcfApCJqMMueQI0Fb68Amflj83+dvAvHawoBpAz+GDjCIyGHzNwnefjsWJ3xiYAqqiQFoWbspGYBdb2/ng==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", - "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.9.tgz", + "integrity": "sha512-5e3FI4Q3M3Pbr21+5xJwCv6ZT6KmGkI0vw3Tozy5ODAQFTIWe37iT8Cr7Ice2Ntb+M3iSKCEWMB1MBgKrW3whg==", "dev": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.7", - "@babel/helper-compilation-targets": "^7.24.7", - "@babel/helper-module-transforms": "^7.24.7", - "@babel/helpers": "^7.24.7", - "@babel/parser": "^7.24.7", + "@babel/generator": "^7.24.9", + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-module-transforms": "^7.24.9", + "@babel/helpers": "^7.24.8", + "@babel/parser": "^7.24.8", "@babel/template": "^7.24.7", - "@babel/traverse": "^7.24.7", - "@babel/types": "^7.24.7", + "@babel/traverse": "^7.24.8", + "@babel/types": "^7.24.9", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -113,12 +110,12 @@ } }, "node_modules/@babel/generator": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", - "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", + "version": "7.24.10", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.10.tgz", + "integrity": "sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==", "dev": true, "dependencies": { - "@babel/types": "^7.24.7", + "@babel/types": "^7.24.9", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" @@ -128,14 +125,14 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", - "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.8.tgz", + "integrity": "sha512-oU+UoqCHdp+nWVDkpldqIQL/i/bvAv53tRqLG/s+cOXxe66zOYLU7ar/Xs3LdmBihrUMEUhwu6dMZwbNOYDwvw==", "dev": true, "dependencies": { - "@babel/compat-data": "^7.24.7", - "@babel/helper-validator-option": "^7.24.7", - "browserslist": "^4.22.2", + "@babel/compat-data": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -218,9 +215,9 @@ } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", - "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.9.tgz", + "integrity": "sha512-oYbh+rtFKj/HwBQkFlUzvcybzklmVdVV3UU+mN7n2t/q3yGHbuVdNxyFvSBO1tfvjyArpHNcWMAzsSPdyI46hw==", "dev": true, "dependencies": { "@babel/helper-environment-visitor": "^7.24.7", @@ -237,9 +234,9 @@ } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", - "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.8.tgz", + "integrity": "sha512-FFWx5142D8h2Mgr/iPVGH5G7w6jDn4jUSpZTyDnQO0Yn7Ks2Kuz6Pci8H6MPCoUJegd/UZQ3tAvfLCxQSnWWwg==", "dev": true, "engines": { "node": ">=6.9.0" @@ -271,9 +268,9 @@ } }, "node_modules/@babel/helper-string-parser": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", - "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", + "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", "dev": true, "engines": { "node": ">=6.9.0" @@ -289,22 +286,22 @@ } }, "node_modules/@babel/helper-validator-option": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", - "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.8.tgz", + "integrity": "sha512-xb8t9tD1MHLungh/AIoWYN+gVHaB9kwlu8gffXGSt3FFEIT7RjS+xWbc2vUD1UTZdIpKj/ab3rdqJ7ufngyi2Q==", "dev": true, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", - "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.8.tgz", + "integrity": "sha512-gV2265Nkcz7weJJfvDoAEVzC1e2OTDpkGbEsebse8koXUJUXPsCMi7sRo/+SPMuMZ9MtUPnGwITTnQnU5YjyaQ==", "dev": true, "dependencies": { "@babel/template": "^7.24.7", - "@babel/types": "^7.24.7" + "@babel/types": "^7.24.8" }, "engines": { "node": ">=6.9.0" @@ -397,9 +394,9 @@ } }, "node_modules/@babel/parser": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", - "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.8.tgz", + "integrity": "sha512-WzfbgXOkGzZiXXCqk43kKwZjzwx4oulxZi3nq2TYL9mOjQv6kYwul9mz6ID36njuL7Xkp6nJEfok848Zj10j/w==", "dev": true, "bin": { "parser": "bin/babel-parser.js" @@ -600,19 +597,19 @@ } }, "node_modules/@babel/traverse": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", - "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz", + "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==", "dev": true, "dependencies": { "@babel/code-frame": "^7.24.7", - "@babel/generator": "^7.24.7", + "@babel/generator": "^7.24.8", "@babel/helper-environment-visitor": "^7.24.7", "@babel/helper-function-name": "^7.24.7", "@babel/helper-hoist-variables": "^7.24.7", "@babel/helper-split-export-declaration": "^7.24.7", - "@babel/parser": "^7.24.7", - "@babel/types": "^7.24.7", + "@babel/parser": "^7.24.8", + "@babel/types": "^7.24.8", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -630,12 +627,12 @@ } }, "node_modules/@babel/types": { - "version": "7.24.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", - "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", + "version": "7.24.9", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.9.tgz", + "integrity": "sha512-xm8XrMKz0IlUdocVbYJe0Z9xEgidU7msskG8BbhnTPK/HZ2z/7FP7ykqPgrUH+C+r414mNfNWam1f2vqOjqjYQ==", "dev": true, "dependencies": { - "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, @@ -937,9 +934,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.23.0.tgz", + "integrity": "sha512-3sG8Zwa5fMcA9bgqB8AfWPQ+HFke6uD3h1s3RIwUNK8EG7a4buxvuFTs3j1IMs2NXAk9F30C/FF4vxRgQCcmoQ==", "cpu": [ "ppc64" ], @@ -949,13 +946,13 @@ "aix" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.23.0.tgz", + "integrity": "sha512-+KuOHTKKyIKgEEqKbGTK8W7mPp+hKinbMBeEnNzjJGyFcWsfrXjSTNluJHCY1RqhxFurdD8uNXQDei7qDlR6+g==", "cpu": [ "arm" ], @@ -965,13 +962,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.23.0.tgz", + "integrity": "sha512-EuHFUYkAVfU4qBdyivULuu03FhJO4IJN9PGuABGrFy4vUuzk91P2d+npxHcFdpUnfYKy0PuV+n6bKIpHOB3prQ==", "cpu": [ "arm64" ], @@ -981,13 +978,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.23.0.tgz", + "integrity": "sha512-WRrmKidLoKDl56LsbBMhzTTBxrsVwTKdNbKDalbEZr0tcsBgCLbEtoNthOW6PX942YiYq8HzEnb4yWQMLQuipQ==", "cpu": [ "x64" ], @@ -997,13 +994,13 @@ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.23.0.tgz", + "integrity": "sha512-YLntie/IdS31H54Ogdn+v50NuoWF5BDkEUFpiOChVa9UnKpftgwzZRrI4J132ETIi+D8n6xh9IviFV3eXdxfow==", "cpu": [ "arm64" ], @@ -1013,13 +1010,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.23.0.tgz", + "integrity": "sha512-IMQ6eme4AfznElesHUPDZ+teuGwoRmVuuixu7sv92ZkdQcPbsNHzutd+rAfaBKo8YK3IrBEi9SLLKWJdEvJniQ==", "cpu": [ "x64" ], @@ -1029,13 +1026,13 @@ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.23.0.tgz", + "integrity": "sha512-0muYWCng5vqaxobq6LB3YNtevDFSAZGlgtLoAc81PjUfiFz36n4KMpwhtAd4he8ToSI3TGyuhyx5xmiWNYZFyw==", "cpu": [ "arm64" ], @@ -1045,13 +1042,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.23.0.tgz", + "integrity": "sha512-XKDVu8IsD0/q3foBzsXGt/KjD/yTKBCIwOHE1XwiXmrRwrX6Hbnd5Eqn/WvDekddK21tfszBSrE/WMaZh+1buQ==", "cpu": [ "x64" ], @@ -1061,13 +1058,13 @@ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.23.0.tgz", + "integrity": "sha512-SEELSTEtOFu5LPykzA395Mc+54RMg1EUgXP+iw2SJ72+ooMwVsgfuwXo5Fn0wXNgWZsTVHwY2cg4Vi/bOD88qw==", "cpu": [ "arm" ], @@ -1077,13 +1074,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.23.0.tgz", + "integrity": "sha512-j1t5iG8jE7BhonbsEg5d9qOYcVZv/Rv6tghaXM/Ug9xahM0nX/H2gfu6X6z11QRTMT6+aywOMA8TDkhPo8aCGw==", "cpu": [ "arm64" ], @@ -1093,13 +1090,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.23.0.tgz", + "integrity": "sha512-P7O5Tkh2NbgIm2R6x1zGJJsnacDzTFcRWZyTTMgFdVit6E98LTxO+v8LCCLWRvPrjdzXHx9FEOA8oAZPyApWUA==", "cpu": [ "ia32" ], @@ -1109,13 +1106,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.23.0.tgz", + "integrity": "sha512-InQwepswq6urikQiIC/kkx412fqUZudBO4SYKu0N+tGhXRWUqAx+Q+341tFV6QdBifpjYgUndV1hhMq3WeJi7A==", "cpu": [ "loong64" ], @@ -1125,13 +1122,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.23.0.tgz", + "integrity": "sha512-J9rflLtqdYrxHv2FqXE2i1ELgNjT+JFURt/uDMoPQLcjWQA5wDKgQA4t/dTqGa88ZVECKaD0TctwsUfHbVoi4w==", "cpu": [ "mips64el" ], @@ -1141,13 +1138,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.23.0.tgz", + "integrity": "sha512-cShCXtEOVc5GxU0fM+dsFD10qZ5UpcQ8AM22bYj0u/yaAykWnqXJDpd77ublcX6vdDsWLuweeuSNZk4yUxZwtw==", "cpu": [ "ppc64" ], @@ -1157,13 +1154,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.23.0.tgz", + "integrity": "sha512-HEtaN7Y5UB4tZPeQmgz/UhzoEyYftbMXrBCUjINGjh3uil+rB/QzzpMshz3cNUxqXN7Vr93zzVtpIDL99t9aRw==", "cpu": [ "riscv64" ], @@ -1173,13 +1170,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.23.0.tgz", + "integrity": "sha512-WDi3+NVAuyjg/Wxi+o5KPqRbZY0QhI9TjrEEm+8dmpY9Xir8+HE/HNx2JoLckhKbFopW0RdO2D72w8trZOV+Wg==", "cpu": [ "s390x" ], @@ -1189,13 +1186,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.23.0.tgz", + "integrity": "sha512-a3pMQhUEJkITgAw6e0bWA+F+vFtCciMjW/LPtoj99MhVt+Mfb6bbL9hu2wmTZgNd994qTAEw+U/r6k3qHWWaOQ==", "cpu": [ "x64" ], @@ -1205,13 +1202,13 @@ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.23.0.tgz", + "integrity": "sha512-cRK+YDem7lFTs2Q5nEv/HHc4LnrfBCbH5+JHu6wm2eP+d8OZNoSMYgPZJq78vqQ9g+9+nMuIsAO7skzphRXHyw==", "cpu": [ "x64" ], @@ -1221,13 +1218,29 @@ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.23.0.tgz", + "integrity": "sha512-suXjq53gERueVWu0OKxzWqk7NxiUWSUlrxoZK7usiF50C6ipColGR5qie2496iKGYNLhDZkPxBI3erbnYkU0rQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.23.0.tgz", + "integrity": "sha512-6p3nHpby0DM/v15IFKMjAaayFhqnXV52aEmv1whZHX56pdkK+MEaLoQWj+H42ssFarP1PcomVhbsR4pkz09qBg==", "cpu": [ "x64" ], @@ -1237,13 +1250,13 @@ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.23.0.tgz", + "integrity": "sha512-BFelBGfrBwk6LVrmFzCq1u1dZbG4zy/Kp93w2+y83Q5UGYF1d8sCzeLI9NXjKyujjBBniQa8R8PzLFAUrSM9OA==", "cpu": [ "x64" ], @@ -1253,13 +1266,13 @@ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.23.0.tgz", + "integrity": "sha512-lY6AC8p4Cnb7xYHuIxQ6iYPe6MfO2CC43XXKo9nBXDb35krYt7KGhQnOkRGar5psxYkircpCqfbNDB4uJbS2jQ==", "cpu": [ "arm64" ], @@ -1269,13 +1282,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.23.0.tgz", + "integrity": "sha512-7L1bHlOTcO4ByvI7OXVI5pNN6HSu6pUQq9yodga8izeuB1KcT2UkHaH6118QJwopExPn0rMHIseCTx1CRo/uNA==", "cpu": [ "ia32" ], @@ -1285,13 +1298,13 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.23.0.tgz", + "integrity": "sha512-Arm+WgUFLUATuoxCJcahGuk6Yj9Pzxd6l11Zb/2aAuv5kWWvvfhLFo2fni4uSK5vzlUdCGZ/BdV5tH8klj8p8g==", "cpu": [ "x64" ], @@ -1301,7 +1314,7 @@ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { @@ -1401,9 +1414,9 @@ } }, "node_modules/@eslint/js": { - "version": "9.6.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.6.0.tgz", - "integrity": "sha512-D9B0/3vNg44ZeWbYMpBoXqNP4j6eQD5vNwIlGAuFRRzK/WtT/jvDQW3Bi9kkf3PMDMlM7Yi+73VLUsn5bJcl8A==", + "version": "9.7.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.7.0.tgz", + "integrity": "sha512-ChuWDQenef8OSFnvuxv0TCVxEwmu3+hPNKvM9B34qpM0rDRbjL8t5QkQeHHeAfsKQjuH9wS82WeCi1J/owatng==", "dev": true, "engines": { "node": "^18.18.0 || ^20.9.0 || >=21.1.0" @@ -2034,9 +2047,9 @@ } }, "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==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true }, "node_modules/@jridgewell/trace-mapping": { @@ -2053,10 +2066,18 @@ "resolved": "packages/client", "link": true }, + "node_modules/@lib/config": { + "resolved": "packages/config", + "link": true + }, "node_modules/@lib/cookies": { "resolved": "packages/cookies", "link": true }, + "node_modules/@lib/jwt": { + "resolved": "packages/jwt", + "link": true + }, "node_modules/@lib/purge": { "resolved": "packages/purge", "link": true @@ -2303,6 +2324,45 @@ "@octokit/openapi-types": "^22.2.0" } }, + "node_modules/@peculiar/asn1-schema": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.8.tgz", + "integrity": "sha512-ULB1XqHKx1WBU/tTFIA+uARuRoBVZ4pNdOA878RDrRbBfBGcSzi5HBkdScC6ZbHn8z7L8gmKCgPC1LHRrP46tA==", + "dev": true, + "dependencies": { + "asn1js": "^3.0.5", + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2" + } + }, + "node_modules/@peculiar/json-schema": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", + "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", + "dev": true, + "dependencies": { + "tslib": "^2.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@peculiar/webcrypto": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.5.0.tgz", + "integrity": "sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg==", + "dev": true, + "dependencies": { + "@peculiar/asn1-schema": "^2.3.8", + "@peculiar/json-schema": "^1.1.12", + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2", + "webcrypto-core": "^1.8.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", @@ -3045,9 +3105,9 @@ } }, "node_modules/@swc/core": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.6.13.tgz", - "integrity": "sha512-eailUYex6fkfaQTev4Oa3mwn0/e3mQU4H8y1WPuImYQESOQDtVrowwUGDSc19evpBbHpKtwM+hw8nLlhIsF+Tw==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.7.0.tgz", + "integrity": "sha512-d4vMzH6ICllDwlPuhset2h8gu/USHdbyfJim+2hQEdxC0UONtfpmu38XBgNqRjStrji1Q5M10jfeUZL3cu1i8g==", "dev": true, "hasInstallScript": true, "peer": true, @@ -3063,16 +3123,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.6.13", - "@swc/core-darwin-x64": "1.6.13", - "@swc/core-linux-arm-gnueabihf": "1.6.13", - "@swc/core-linux-arm64-gnu": "1.6.13", - "@swc/core-linux-arm64-musl": "1.6.13", - "@swc/core-linux-x64-gnu": "1.6.13", - "@swc/core-linux-x64-musl": "1.6.13", - "@swc/core-win32-arm64-msvc": "1.6.13", - "@swc/core-win32-ia32-msvc": "1.6.13", - "@swc/core-win32-x64-msvc": "1.6.13" + "@swc/core-darwin-arm64": "1.7.0", + "@swc/core-darwin-x64": "1.7.0", + "@swc/core-linux-arm-gnueabihf": "1.7.0", + "@swc/core-linux-arm64-gnu": "1.7.0", + "@swc/core-linux-arm64-musl": "1.7.0", + "@swc/core-linux-x64-gnu": "1.7.0", + "@swc/core-linux-x64-musl": "1.7.0", + "@swc/core-win32-arm64-msvc": "1.7.0", + "@swc/core-win32-ia32-msvc": "1.7.0", + "@swc/core-win32-x64-msvc": "1.7.0" }, "peerDependencies": { "@swc/helpers": "*" @@ -3084,9 +3144,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.6.13.tgz", - "integrity": "sha512-SOF4buAis72K22BGJ3N8y88mLNfxLNprTuJUpzikyMGrvkuBFNcxYtMhmomO0XHsgLDzOJ+hWzcgjRNzjMsUcQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.7.0.tgz", + "integrity": "sha512-2ylhM7f0HwUwLrFYZAe/dse8PCbPsYcJS3Dt7Q8NT3PUn7vy6QOMxNcOPPuDrnmaXqQQO3oxdmRapguTxaat9g==", "cpu": [ "arm64" ], @@ -3101,9 +3161,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.6.13.tgz", - "integrity": "sha512-AW8akFSC+tmPE6YQQvK9S2A1B8pjnXEINg+gGgw0KRUUXunvu1/OEOeC5L2Co1wAwhD7bhnaefi06Qi9AiwOag==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.7.0.tgz", + "integrity": "sha512-SgVnN4gT1Rb9YfTkp4FCUITqSs7Yj0uB2SUciu5CV3HuGvS5YXCUzh+KrwpLFtx8NIgivISKcNnb41mJi98X8Q==", "cpu": [ "x64" ], @@ -3118,9 +3178,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.6.13.tgz", - "integrity": "sha512-f4gxxvDXVUm2HLYXRd311mSrmbpQF2MZ4Ja6XCQz1hWAxXdhRl1gpnZ+LH/xIfGSwQChrtLLVrkxdYUCVuIjFg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.7.0.tgz", + "integrity": "sha512-+Z9Dayart1iKJQEJJ9N/KS4z5EdXJE3WPFikY0jonKTo4Dd8RuyVz5yLvqcIMeVdz/SwximATaL6iJXw7hZS9A==", "cpu": [ "arm" ], @@ -3135,9 +3195,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.6.13.tgz", - "integrity": "sha512-Nf/eoW2CbG8s+9JoLtjl9FByBXyQ5cjdBsA4efO7Zw4p+YSuXDgc8HRPC+E2+ns0praDpKNZtLvDtmF2lL+2Gg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.7.0.tgz", + "integrity": "sha512-UnLrCiZ1EI4shznJn0xP6DLgsXUSwtfsdgHhGYCrvbgVBBve3S9iFgVFEB3SPl7Q/TdowNbrN4zHU0oChfiNfw==", "cpu": [ "arm64" ], @@ -3152,9 +3212,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.6.13.tgz", - "integrity": "sha512-2OysYSYtdw79prJYuKIiux/Gj0iaGEbpS2QZWCIY4X9sGoETJ5iMg+lY+YCrIxdkkNYd7OhIbXdYFyGs/w5LDg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.7.0.tgz", + "integrity": "sha512-H724UANA+ptsfwKRr9mnaDa9cb5fw0oFysiGKTgb3DMYcgk3Od0jMTnXVPFSVpo7FlmyxeC9K8ueUPBOoOK6XA==", "cpu": [ "arm64" ], @@ -3169,9 +3229,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.6.13.tgz", - "integrity": "sha512-PkR4CZYJNk5hcd2+tMWBpnisnmYsUzazI1O5X7VkIGFcGePTqJ/bWlfUIVVExWxvAI33PQFzLbzmN5scyIUyGQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.7.0.tgz", + "integrity": "sha512-SY3HA0K0Dpqt1HIfMLGpwL4hd4UaL2xHP5oZXPlRQPhUDZrbb4PbI3ZJnh66c63eL4ZR8EJ+HRFI0Alx5p69Zw==", "cpu": [ "x64" ], @@ -3186,9 +3246,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.6.13.tgz", - "integrity": "sha512-OdsY7wryTxCKwGQcwW9jwWg3cxaHBkTTHi91+5nm7hFPpmZMz1HivJrWAMwVE7iXFw+M4l6ugB/wCvpYrUAAjA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.7.0.tgz", + "integrity": "sha512-cEJ2ebtV1v/5Ilb55E05J6F5SrHKQWzUttIhR5Mkayyo+yvPslcpByuFC3D+J7X1ebziTOBpWuMpUdjLfh3SMQ==", "cpu": [ "x64" ], @@ -3203,9 +3263,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.6.13.tgz", - "integrity": "sha512-ap6uNmYjwk9M/+bFEuWRNl3hq4VqgQ/Lk+ID/F5WGqczNr0L7vEf+pOsRAn0F6EV+o/nyb3ePt8rLhE/wjHpPg==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.7.0.tgz", + "integrity": "sha512-ecQOOmzEssz+m0pR4xDYCGuvn3E/l0nQ3tk5jp1NA1lsAy4bMV0YbYCHjptYvWL/UjhIerIp3IlCJ8x5DodSog==", "cpu": [ "arm64" ], @@ -3220,9 +3280,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.6.13.tgz", - "integrity": "sha512-IJ8KH4yIUHTnS/U1jwQmtbfQals7zWPG0a9hbEfIr4zI0yKzjd83lmtS09lm2Q24QBWOCFGEEbuZxR4tIlvfzA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.7.0.tgz", + "integrity": "sha512-gz81seZkRn3zMnVOc7L5k6F4vQC82gIxmHiL+GedK+A37XI/X26AASU3zxvORnqQbwQYXQ+AEVckxBmFlz3v2g==", "cpu": [ "ia32" ], @@ -3237,9 +3297,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.6.13", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.6.13.tgz", - "integrity": "sha512-f6/sx6LMuEnbuxtiSL/EkR0Y6qUHFw1XVrh6rwzKXptTipUdOY+nXpKoh+1UsBm/r7H0/5DtOdrn3q5ZHbFZjQ==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.7.0.tgz", + "integrity": "sha512-b5Fd1xEOw9uqBpj2lqsaR4Iq9UhiL84hNDcEsi6DQA7Y1l85waQAslTbS0E4/pJ1PISAs0jW0zIGLco1eaWBOg==", "cpu": [ "x64" ], @@ -3432,9 +3492,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.14.10", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.10.tgz", - "integrity": "sha512-MdiXf+nDuMvY0gJKxyfZ7/6UFsETO7mGKF54MVD/ekJS6HdFtpZFBgrh6Pseu64XTb2MLyFPlbW6hj8HYRQNOQ==", + "version": "20.14.11", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.11.tgz", + "integrity": "sha512-kprQpL8MMeszbz6ojB5/tU8PLN4kesnN8Gjzw349rDlNgsSzg90lAVj3llK99Dh7JON+t9AuscPPFW6mPbTnSA==", "dev": true, "dependencies": { "undici-types": "~5.26.4" @@ -3468,16 +3528,16 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.0.tgz", - "integrity": "sha512-py1miT6iQpJcs1BiJjm54AMzeuMPBSPuKPlnT8HlfudbcS5rYeX5jajpLf3mrdRh9dA/Ec2FVUY0ifeVNDIhZw==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.16.1.tgz", + "integrity": "sha512-SxdPak/5bO0EnGktV05+Hq8oatjAYVY3Zh2bye9pGZy6+jwyR3LG3YKkV4YatlsgqXP28BTeVm9pqwJM96vf2A==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.10.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/type-utils": "7.16.0", - "@typescript-eslint/utils": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", + "@typescript-eslint/scope-manager": "7.16.1", + "@typescript-eslint/type-utils": "7.16.1", + "@typescript-eslint/utils": "7.16.1", + "@typescript-eslint/visitor-keys": "7.16.1", "graphemer": "^1.4.0", "ignore": "^5.3.1", "natural-compare": "^1.4.0", @@ -3501,15 +3561,15 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.0.tgz", - "integrity": "sha512-ar9E+k7CU8rWi2e5ErzQiC93KKEFAXA2Kky0scAlPcxYblLt8+XZuHUZwlyfXILyQa95P6lQg+eZgh/dDs3+Vw==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.16.1.tgz", + "integrity": "sha512-u+1Qx86jfGQ5i4JjK33/FnawZRpsLxRnKzGE6EABZ40KxVT/vWsiZFEBBHjFOljmmV3MBYOHEKi0Jm9hbAOClA==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", + "@typescript-eslint/scope-manager": "7.16.1", + "@typescript-eslint/types": "7.16.1", + "@typescript-eslint/typescript-estree": "7.16.1", + "@typescript-eslint/visitor-keys": "7.16.1", "debug": "^4.3.4" }, "engines": { @@ -3529,13 +3589,13 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.0.tgz", - "integrity": "sha512-8gVv3kW6n01Q6TrI1cmTZ9YMFi3ucDT7i7aI5lEikk2ebk1AEjrwX8MDTdaX5D7fPXMBLvnsaa0IFTAu+jcfOw==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.16.1.tgz", + "integrity": "sha512-nYpyv6ALte18gbMz323RM+vpFpTjfNdyakbf3nsLvF43uF9KeNC289SUEW3QLZ1xPtyINJ1dIsZOuWuSRIWygw==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0" + "@typescript-eslint/types": "7.16.1", + "@typescript-eslint/visitor-keys": "7.16.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -3546,13 +3606,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.0.tgz", - "integrity": "sha512-j0fuUswUjDHfqV/UdW6mLtOQQseORqfdmoBNDFOqs9rvNVR2e+cmu6zJu/Ku4SDuqiJko6YnhwcL8x45r8Oqxg==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.16.1.tgz", + "integrity": "sha512-rbu/H2MWXN4SkjIIyWcmYBjlp55VT+1G3duFOIukTNFxr9PI35pLc2ydwAfejCEitCv4uztA07q0QWanOHC7dA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "7.16.0", - "@typescript-eslint/utils": "7.16.0", + "@typescript-eslint/typescript-estree": "7.16.1", + "@typescript-eslint/utils": "7.16.1", "debug": "^4.3.4", "ts-api-utils": "^1.3.0" }, @@ -3573,9 +3633,9 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.0.tgz", - "integrity": "sha512-fecuH15Y+TzlUutvUl9Cc2XJxqdLr7+93SQIbcZfd4XRGGKoxyljK27b+kxKamjRkU7FYC6RrbSCg0ALcZn/xw==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.16.1.tgz", + "integrity": "sha512-AQn9XqCzUXd4bAVEsAXM/Izk11Wx2u4H3BAfQVhSfzfDOm/wAON9nP7J5rpkCxts7E5TELmN845xTUCQrD1xIQ==", "dev": true, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -3586,13 +3646,13 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.0.tgz", - "integrity": "sha512-a5NTvk51ZndFuOLCh5OaJBELYc2O3Zqxfl3Js78VFE1zE46J2AaVuW+rEbVkQznjkmlzWsUI15BG5tQMixzZLw==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.16.1.tgz", + "integrity": "sha512-0vFPk8tMjj6apaAZ1HlwM8w7jbghC8jc1aRNJG5vN8Ym5miyhTQGMqU++kuBFDNKe9NcPeZ6x0zfSzV8xC1UlQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/visitor-keys": "7.16.0", + "@typescript-eslint/types": "7.16.1", + "@typescript-eslint/visitor-keys": "7.16.1", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -3667,15 +3727,15 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.0.tgz", - "integrity": "sha512-PqP4kP3hb4r7Jav+NiRCntlVzhxBNWq6ZQ+zQwII1y/G/1gdIPeYDCKr2+dH6049yJQsWZiHU6RlwvIFBXXGNA==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.16.1.tgz", + "integrity": "sha512-WrFM8nzCowV0he0RlkotGDujx78xudsxnGMBHI88l5J8wEhED6yBwaSLP99ygfrzAjsQvcYQ94quDwI0d7E1fA==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", - "@typescript-eslint/scope-manager": "7.16.0", - "@typescript-eslint/types": "7.16.0", - "@typescript-eslint/typescript-estree": "7.16.0" + "@typescript-eslint/scope-manager": "7.16.1", + "@typescript-eslint/types": "7.16.1", + "@typescript-eslint/typescript-estree": "7.16.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -3689,12 +3749,12 @@ } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.0.tgz", - "integrity": "sha512-rMo01uPy9C7XxG7AFsxa8zLnWXTF8N3PYclekWSrurvhwiw1eW88mrKiAYe6s53AUY57nTRz8dJsuuXdkAhzCg==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.16.1.tgz", + "integrity": "sha512-Qlzzx4sE4u3FsHTPQAAQFJFNOuqtuY0LFrZHwQ8IHK705XxBiWOFkfKRWu6niB7hwfgnwIpO4jTC75ozW1PHWg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "7.16.0", + "@typescript-eslint/types": "7.16.1", "eslint-visitor-keys": "^3.4.3" }, "engines": { @@ -3770,15 +3830,15 @@ } }, "node_modules/ajv": { - "version": "8.16.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", - "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", + "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "dependencies": { "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2", - "uri-js": "^4.4.1" + "require-from-string": "^2.0.2" }, "funding": { "type": "github", @@ -3888,6 +3948,26 @@ "node": ">=0.10.0" } }, + "node_modules/asn1js": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", + "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", + "dev": true, + "dependencies": { + "pvtsutils": "^1.3.2", + "pvutils": "^1.1.3", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==", + "dev": true + }, "node_modules/babel-jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", @@ -4066,9 +4146,9 @@ } }, "node_modules/browserslist": { - "version": "4.23.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", - "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", + "version": "4.23.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.2.tgz", + "integrity": "sha512-qkqSyistMYdxAcw+CzbZwlBy8AGmS/eEWs+sEV5TnLRGDOL+C5M2EnH6tlZyg0YoAxGJAFKh61En9BR941GnHA==", "dev": true, "funding": [ { @@ -4085,10 +4165,10 @@ } ], "dependencies": { - "caniuse-lite": "^1.0.30001629", - "electron-to-chromium": "^1.4.796", + "caniuse-lite": "^1.0.30001640", + "electron-to-chromium": "^1.4.820", "node-releases": "^2.0.14", - "update-browserslist-db": "^1.0.16" + "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" @@ -4125,9 +4205,9 @@ "dev": true }, "node_modules/bundle-require": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-4.2.1.tgz", - "integrity": "sha512-7Q/6vkyYAwOmQNRw75x+4yRtZCZJXUDmHHlFdkiV0wgv/reNjtJwpu1jPJ0w2kbEpIM0uoKI3S4/f39dU7AjSA==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/bundle-require/-/bundle-require-5.0.0.tgz", + "integrity": "sha512-GuziW3fSSmopcx4KRymQEJVbZUfqlCqcq7dvs6TYwKRZiegK/2buMxQTPs6MGlNv50wms1699qYO54R8XfRX4w==", "dev": true, "dependencies": { "load-tsconfig": "^0.2.3" @@ -4136,7 +4216,7 @@ "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "peerDependencies": { - "esbuild": ">=0.17" + "esbuild": ">=0.18" } }, "node_modules/cac": { @@ -4184,9 +4264,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001640", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz", - "integrity": "sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA==", + "version": "1.0.30001642", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001642.tgz", + "integrity": "sha512-3XQ0DoRgLijXJErLSl+bLnJ+Et4KqV1PY6JJBGAFlsNsz31zeAIncyeZfLCabHK/jtSh+671RM9YMldxjUPZtA==", "dev": true, "funding": [ { @@ -4405,6 +4485,15 @@ "proto-list": "~1.2.1" } }, + "node_modules/consola": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.2.3.tgz", + "integrity": "sha512-I5qxpzLv+sJhTVEoLYNcTW+bThDCPsit0vLNKShZx6rLtpilNpmmeTPaeqJb9ZE9dV3DGaeby6Vuhrw38WjeyQ==", + "dev": true, + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, "node_modules/conventional-changelog-angular": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-7.0.0.tgz", @@ -4809,10 +4898,25 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "node_modules/ejs": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", + "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==", + "dev": true, + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/electron-to-chromium": { - "version": "1.4.820", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.820.tgz", - "integrity": "sha512-kK/4O/YunacfboFEk/BDf7VO1HoPmDudLTJAU9NmXIOSjsV7qVIX3OrI4REZo0VmdqhcpUcncQc6N8Q3aEXlHg==", + "version": "1.4.830", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.830.tgz", + "integrity": "sha512-TrPKKH20HeN0J1LHzsYLs2qwXrp8TF4nHdu4sq61ozGbzMpWhI7iIOPYPPkxeq1azMT9PZ8enPFcftbs/Npcjg==", "dev": true }, "node_modules/emittery": { @@ -4978,41 +5082,42 @@ } }, "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", + "version": "0.23.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.23.0.tgz", + "integrity": "sha512-1lvV17H2bMYda/WaFb2jLPeHU3zml2k4/yagNMG8Q/YtfMjCwEUZa2eXXMgZTVSL5q1n4H7sQ0X6CdJDqqeCFA==", "dev": true, "hasInstallScript": true, "bin": { "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" + "@esbuild/aix-ppc64": "0.23.0", + "@esbuild/android-arm": "0.23.0", + "@esbuild/android-arm64": "0.23.0", + "@esbuild/android-x64": "0.23.0", + "@esbuild/darwin-arm64": "0.23.0", + "@esbuild/darwin-x64": "0.23.0", + "@esbuild/freebsd-arm64": "0.23.0", + "@esbuild/freebsd-x64": "0.23.0", + "@esbuild/linux-arm": "0.23.0", + "@esbuild/linux-arm64": "0.23.0", + "@esbuild/linux-ia32": "0.23.0", + "@esbuild/linux-loong64": "0.23.0", + "@esbuild/linux-mips64el": "0.23.0", + "@esbuild/linux-ppc64": "0.23.0", + "@esbuild/linux-riscv64": "0.23.0", + "@esbuild/linux-s390x": "0.23.0", + "@esbuild/linux-x64": "0.23.0", + "@esbuild/netbsd-x64": "0.23.0", + "@esbuild/openbsd-arm64": "0.23.0", + "@esbuild/openbsd-x64": "0.23.0", + "@esbuild/sunos-x64": "0.23.0", + "@esbuild/win32-arm64": "0.23.0", + "@esbuild/win32-ia32": "0.23.0", + "@esbuild/win32-x64": "0.23.0" } }, "node_modules/escalade": { @@ -5355,6 +5460,12 @@ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", "dev": true }, + "node_modules/fast-uri": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz", + "integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw==", + "dev": true + }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", @@ -5413,6 +5524,36 @@ "node": "^10.12.0 || >=12.0.0" } }, + "node_modules/filelist": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz", + "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==", + "dev": true, + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/filelist/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/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", @@ -5889,12 +6030,12 @@ } }, "node_modules/husky": { - "version": "9.0.11", - "resolved": "https://registry.npmjs.org/husky/-/husky-9.0.11.tgz", - "integrity": "sha512-AB6lFlbwwyIqMdHYhwPe+kjOC3Oc5P3nThEoW/AaO2BX3vJDjWPFxYLxokUZOo6RNX20He3AaT8sESs9NJcmEw==", + "version": "9.1.1", + "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.1.tgz", + "integrity": "sha512-fCqlqLXcBnXa/TJXmT93/A36tJsjdJkibQ1MuIiFyCCYUlpYpIaj2mv1w+3KR6Rzu1IC3slFTje5f6DUp2A2rg==", "dev": true, "bin": { - "husky": "bin.mjs" + "husky": "bin.js" }, "engines": { "node": ">=18" @@ -6044,9 +6185,9 @@ } }, "node_modules/is-core-module": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", - "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.0.tgz", + "integrity": "sha512-Dd+Lb2/zvk9SKy1TGCt1wFJFo/MWBPMX5x7KcvLajWTGuomczdQX61PvY5yK6SVACwpoexWo81IfFyoKY2QnTA==", "dev": true, "dependencies": { "hasown": "^2.0.2" @@ -6264,16 +6405,13 @@ } }, "node_modules/jackspeak": { - "version": "3.4.2", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.2.tgz", - "integrity": "sha512-qH3nOSj8q/8+Eg8LUPOq3C+6HWkpUioIjDsq1+D4zY91oZvpPttw8GwtF1nReRYKXl+1AORyFqtm2f5Q1SB6/Q==", + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", "dev": true, "dependencies": { "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": "14 >=14.21 || 16 >=16.20 || >=18" - }, "funding": { "url": "https://github.com/sponsors/isaacs" }, @@ -6281,6 +6419,24 @@ "@pkgjs/parseargs": "^0.11.0" } }, + "node_modules/jake": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz", + "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==", + "dev": true, + "dependencies": { + "async": "^3.2.3", + "chalk": "^4.0.2", + "filelist": "^1.0.4", + "minimatch": "^3.1.2" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/java-properties": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/java-properties/-/java-properties-1.0.2.tgz", @@ -7715,9 +7871,9 @@ "dev": true }, "node_modules/node-releases": { - "version": "2.0.14", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", - "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "version": "2.0.17", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.17.tgz", + "integrity": "sha512-Ww6ZlOiEQfPfXM45v17oabk77Z7mg5bOt7AjDyzy7RjK9OrLrLC8dyZQoAPEOtFX9SaNf1Tdvr5gRJWdTJj7GA==", "dev": true }, "node_modules/normalize-package-data": { @@ -11284,13 +11440,10 @@ } }, "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.2.tgz", - "integrity": "sha512-voV4dDrdVZVNz84n39LFKDaRzfwhdzJ7akpyXfTMxCgRUp07U3lcJUXRlhTKP17rgt09sUzLi5iCitpEAr+6ug==", - "dev": true, - "engines": { - "node": "14 || 16 || 18 || 20 || >=22" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/path-type": { "version": "4.0.0", @@ -11482,9 +11635,9 @@ } }, "node_modules/postcss-load-config": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", - "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", + "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", "dev": true, "funding": [ { @@ -11497,21 +11650,28 @@ } ], "dependencies": { - "lilconfig": "^3.0.0", - "yaml": "^2.3.4" + "lilconfig": "^3.1.1" }, "engines": { - "node": ">= 14" + "node": ">= 18" }, "peerDependencies": { + "jiti": ">=1.21.0", "postcss": ">=8.0.9", - "ts-node": ">=9.0.0" + "tsx": "^4.8.1", + "yaml": "^2.4.2" }, "peerDependenciesMeta": { + "jiti": { + "optional": true + }, "postcss": { "optional": true }, - "ts-node": { + "tsx": { + "optional": true + }, + "yaml": { "optional": true } } @@ -11526,9 +11686,9 @@ } }, "node_modules/prettier": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", - "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.3.tgz", + "integrity": "sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==", "dev": true, "bin": { "prettier": "bin/prettier.cjs" @@ -11616,6 +11776,24 @@ } ] }, + "node_modules/pvtsutils": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.5.tgz", + "integrity": "sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==", + "dev": true, + "dependencies": { + "tslib": "^2.6.1" + } + }, + "node_modules/pvutils": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", + "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", + "dev": true, + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/q": { "version": "1.5.1", "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", @@ -11792,9 +11970,9 @@ } }, "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.21.0.tgz", - "integrity": "sha512-ADn2w7hVPcK6w1I0uWnM//y1rLXZhzB9mr0a3OirzclKF1Wp6VzevUmzz/NRAWunOT6E8HrnpGY7xOfc6K57fA==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.22.1.tgz", + "integrity": "sha512-9tHNEa0Ov81YOopiVkcCJVz5TM6AEQ+CHHjFIktqPnE3NV0AHIkx+gh9tiCl58m/66wWxkOC9eltpa75J4lQPA==", "dev": true, "engines": { "node": ">=16" @@ -11846,13 +12024,10 @@ } }, "node_modules/read-pkg/node_modules/lru-cache": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.2.tgz", - "integrity": "sha512-voV4dDrdVZVNz84n39LFKDaRzfwhdzJ7akpyXfTMxCgRUp07U3lcJUXRlhTKP17rgt09sUzLi5iCitpEAr+6ug==", - "dev": true, - "engines": { - "node": "14 || 16 || 18 || 20 || >=22" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/read-pkg/node_modules/normalize-package-data": { "version": "6.0.2", @@ -11900,9 +12075,9 @@ } }, "node_modules/read-pkg/node_modules/type-fest": { - "version": "4.21.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.21.0.tgz", - "integrity": "sha512-ADn2w7hVPcK6w1I0uWnM//y1rLXZhzB9mr0a3OirzclKF1Wp6VzevUmzz/NRAWunOT6E8HrnpGY7xOfc6K57fA==", + "version": "4.22.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.22.1.tgz", + "integrity": "sha512-9tHNEa0Ov81YOopiVkcCJVz5TM6AEQ+CHHjFIktqPnE3NV0AHIkx+gh9tiCl58m/66wWxkOC9eltpa75J4lQPA==", "dev": true, "engines": { "node": ">=16" @@ -12326,13 +12501,10 @@ } }, "node_modules/semantic-release/node_modules/lru-cache": { - "version": "10.4.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.2.tgz", - "integrity": "sha512-voV4dDrdVZVNz84n39LFKDaRzfwhdzJ7akpyXfTMxCgRUp07U3lcJUXRlhTKP17rgt09sUzLi5iCitpEAr+6ug==", - "dev": true, - "engines": { - "node": "14 || 16 || 18 || 20 || >=22" - } + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true }, "node_modules/semantic-release/node_modules/mimic-fn": { "version": "4.0.0", @@ -13162,12 +13334,13 @@ "dev": true }, "node_modules/ts-jest": { - "version": "29.2.0", - "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.0.tgz", - "integrity": "sha512-eFmkE9MG0+oT6nqSOcUwL+2UUmK2IvhhUV8hFDsCHnc++v2WCCbQQZh5vvjsa8sgOY/g9T0325hmkEmi6rninA==", + "version": "29.2.3", + "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.3.tgz", + "integrity": "sha512-yCcfVdiBFngVz9/keHin9EnsrQtQtEu3nRykNy9RVp+FiPFFbPJ3Sg6Qg4+TkmH0vMP5qsTKgXSsk80HRwvdgQ==", "dev": true, "dependencies": { "bs-logger": "0.x", + "ejs": "^3.1.10", "fast-json-stable-stringify": "2.x", "jest-util": "^29.0.0", "json5": "^2.2.3", @@ -13260,25 +13433,32 @@ } } }, + "node_modules/tslib": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "dev": true + }, "node_modules/tsup": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.1.0.tgz", - "integrity": "sha512-UFdfCAXukax+U6KzeTNO2kAARHcWxmKsnvSPXUcfA1D+kU05XDccCrkffCQpFaWDsZfV0jMyTsxU39VfCp6EOg==", + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/tsup/-/tsup-8.2.0.tgz", + "integrity": "sha512-XoarnVlfXxbv8ODHtxUq8D2XPc9luX+pamnp1kHSKLknKCDcX0Rkc21NHdbpugH6hKoNiETXypKKVgVu46vVRg==", "dev": true, "dependencies": { - "bundle-require": "^4.0.0", - "cac": "^6.7.12", - "chokidar": "^3.5.1", - "debug": "^4.3.1", - "esbuild": "^0.21.4", - "execa": "^5.0.0", - "globby": "^11.0.3", - "joycon": "^3.0.1", - "postcss-load-config": "^4.0.1", + "bundle-require": "^5.0.0", + "cac": "^6.7.14", + "chokidar": "^3.6.0", + "consola": "^3.2.3", + "debug": "^4.3.5", + "esbuild": "^0.23.0", + "execa": "^5.1.1", + "globby": "^11.1.0", + "joycon": "^3.1.1", + "postcss-load-config": "^6.0.1", "resolve-from": "^5.0.0", - "rollup": "^4.0.2", + "rollup": "^4.18.1", "source-map": "0.8.0-beta.0", - "sucrase": "^3.20.3", + "sucrase": "^3.35.0", "tree-kill": "^1.2.2" }, "bin": { @@ -13397,14 +13577,14 @@ } }, "node_modules/typescript-eslint": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.16.0.tgz", - "integrity": "sha512-kaVRivQjOzuoCXU6+hLnjo3/baxyzWVO5GrnExkFzETRYJKVHYkrJglOu2OCm8Hi9RPDWX1PTNNTpU5KRV0+RA==", + "version": "7.16.1", + "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-7.16.1.tgz", + "integrity": "sha512-889oE5qELj65q/tGeOSvlreNKhimitFwZqQ0o7PcWC7/lgRkAMknznsCsV8J8mZGTP/Z+cIbX8accf2DE33hrA==", "dev": true, "dependencies": { - "@typescript-eslint/eslint-plugin": "7.16.0", - "@typescript-eslint/parser": "7.16.0", - "@typescript-eslint/utils": "7.16.0" + "@typescript-eslint/eslint-plugin": "7.16.1", + "@typescript-eslint/parser": "7.16.1", + "@typescript-eslint/utils": "7.16.1" }, "engines": { "node": "^18.18.0 || >=20.0.0" @@ -13423,9 +13603,9 @@ } }, "node_modules/uglify-js": { - "version": "3.18.0", - "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.18.0.tgz", - "integrity": "sha512-SyVVbcNBCk0dzr9XL/R/ySrmYf0s372K6/hFklzgcp2lBFyXtw4I7BOdDjlLhE1aVqaI/SHWXWmYdlZxuyF38A==", + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.0.tgz", + "integrity": "sha512-wNKHUY2hYYkf6oSFfhwwiHo4WCHzHmzcXsqXYTN9ja3iApYIFbb2U6ics9hBcYLHcYGQoAlwnZlTrf3oF+BL/Q==", "dev": true, "optional": true, "bin": { @@ -13576,6 +13756,19 @@ "makeerror": "1.0.12" } }, + "node_modules/webcrypto-core": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.8.0.tgz", + "integrity": "sha512-kR1UQNH8MD42CYuLzvibfakG5Ew5seG85dMMoAM/1LqvckxaF6pUiidLuraIu4V+YCIFabYecUZAW0TuxAoaqw==", + "dev": true, + "dependencies": { + "@peculiar/asn1-schema": "^2.3.8", + "@peculiar/json-schema": "^1.1.12", + "asn1js": "^3.0.1", + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2" + } + }, "node_modules/webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", @@ -13701,18 +13894,6 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true }, - "node_modules/yaml": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", - "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", - "dev": true, - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -13775,6 +13956,11 @@ "version": "1.0.0", "license": "MIT" }, + "packages/config": { + "name": "@lib/config", + "version": "1.0.0", + "license": "MIT" + }, "packages/cookies": { "name": "@lib/cookies", "version": "1.0.0", @@ -13787,6 +13973,20 @@ "ts-node": "^10.9.2" } }, + "packages/jwt": { + "name": "@lib/jwt", + "version": "1.0.0", + "license": "MIT", + "devDependencies": { + "@jest/globals": "^29.7.0", + "@peculiar/webcrypto": "^1.5.0", + "@types/jest": "^29.5.12", + "jest": "^29.7.0", + "ts-jest": "^29.2.2", + "ts-node": "^10.9.2", + "typescript": "^5.5.3" + } + }, "packages/purge": { "name": "@lib/purge", "version": "1.0.0", diff --git a/package.json b/package.json index 7fe5621..414f271 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "azion", - "version": "1.3.0", + "version": "1.4.0-stage.1", "description": "Azion Packages for Edge Computing.", "scripts": { "prepare": "husky", @@ -95,6 +95,11 @@ "import": "./packages/cookies/dist/index.mjs", "types": "./packages/cookies/dist/index.d.ts" }, + "./jwt": { + "require": "./packages/jwt/dist/index.js", + "import": "./packages/jwt/dist/index.mjs", + "types": "./packages/jwt/dist/index.d.ts" + }, "./purge": { "require": "./packages/purge/dist/index.js", "import": "./packages/purge/dist/index.mjs", @@ -128,6 +133,9 @@ "cookies": [ "./packages/cookies/dist/index.d.ts" ], + "jwt": [ + "./packages/jwt/dist/index.d.ts" + ], "router": [ "./packages/router/dist/index.d.ts" ], diff --git a/packages/jwt/.gitignore b/packages/jwt/.gitignore new file mode 100644 index 0000000..9b3e7b2 --- /dev/null +++ b/packages/jwt/.gitignore @@ -0,0 +1,8 @@ +# dependencies +node_modules + +# builded +dist + +# mac files +.DS_Store \ No newline at end of file diff --git a/packages/jwt/README.md b/packages/jwt/README.md new file mode 100644 index 0000000..8b6b3df --- /dev/null +++ b/packages/jwt/README.md @@ -0,0 +1,218 @@ +# Azion JWT Library + +The Azion JWT Library provides utility functions for signing, verifying, and decoding JSON Web Tokens (JWTs). This library ensures ease of use and security when handling JWTs in web applications. + +## Table of Contents + +- [Installation](#installation) +- [Usage](#usage) + - [Sign JWT](#sign-jwt) + - [Verify JWT](#verify-jwt) + - [Decode JWT](#decode-jwt) +- [API Reference](#api-reference) + - [`sign`](#sign) + - [`verify`](#verify) + - [`decode`](#decode) +- [Types](#types) + - [`JWTPayload`](#jwtpayload) + - [`TokenHeader`](#tokenheader) +- [Errors](#errors) + - [`JwtAlgorithmNotImplemented`](#jwtalgorithmnotimplemented) + - [`JwtTokenInvalid`](#jwttokeninvalid) + - [`JwtTokenNotBefore`](#jwttokennotbefore) + - [`JwtTokenExpired`](#jwttokenexpired) + - [`JwtTokenIssuedAt`](#jwttokenissuedat) + - [`JwtHeaderInvalid`](#jwtheaderinvalid) + - [`JwtTokenSignatureMismatched`](#jwttokensignaturemismatched) +- [Contributing](#contributing) + +## Installation + +Install the package using npm or yarn: + +```sh +npm install azion +``` + +or + +```sh +yarn add azion +``` + +## Usage + +### Sign JWT + +**JavaScript:** + +```javascript +import { sign } from 'azion/jwt'; + +const privateKey = 'your-private-key'; +const payload = { userId: 123, exp: Math.floor(Date.now() / 1000) + 3600 }; // 1 hour expiration +sign(payload, privateKey).then((token) => console.log(token)); // Outputs the signed JWT +``` + +**TypeScript:** + +```typescript +import { sign } from 'azion/jwt'; +import type { JWTPayload } from 'azion/jwt/types'; + +const privateKey: string = 'your-private-key'; +const payload: JWTPayload = { userId: 123, exp: Math.floor(Date.now() / 1000) + 3600 }; // 1 hour expiration +sign(payload, privateKey).then((token: string) => console.log(token)); // Outputs the signed JWT +``` + +### Verify JWT + +**JavaScript:** + +```javascript +import { verify } from 'azion/jwt'; + +const publicKey = 'your-public-key'; +const token = 'your-jwt-token'; +verify(token, publicKey) + .then((payload) => console.log(payload)) + .catch((err) => console.error(err)); // Outputs the payload if verification is successful +``` + +**TypeScript:** + +```typescript +import { verify } from 'azion/jwt'; +import type { JWTPayload } from 'azion/jwt/types'; + +const publicKey: string = 'your-public-key'; +const token: string = 'your-jwt-token'; +verify(token, publicKey) + .then((payload: JWTPayload) => console.log(payload)) + .catch((err) => console.error(err)); // Outputs the payload if verification is successful +``` + +### Decode JWT + +**JavaScript:** + +```javascript +import { decode } from 'azion/jwt'; + +const token = 'your-jwt-token'; +const { header, payload } = decode(token); +console.log(header, payload); // Outputs the decoded header and payload +``` + +**TypeScript:** + +```typescript +import { decode } from 'azion/jwt'; +import type { TokenHeader, JWTPayload } from 'azion/jwt/types'; + +const token: string = 'your-jwt-token'; +const { header, payload }: { header: TokenHeader; payload: JWTPayload } = decode(token); +console.log(header, payload); // Outputs the decoded header and payload +``` + +## API Reference + +### `sign` + +Signs a JWT payload with the specified algorithm and private key. + +**Parameters:** + +- `payload: JWTPayload` - The payload to be signed. +- `privateKey: SignatureKey` - The private key used for signing. +- `alg?: SignatureAlgorithm` - The algorithm to use for signing (default is `'HS256'`). + +**Returns:** + +- `Promise` - The signed JWT. + +### `verify` + +Verifies a JWT using the specified public key and algorithm. + +**Parameters:** + +- `token: string` - The JWT to verify. +- `publicKey: SignatureKey` - The public key used for verification. +- `alg?: SignatureAlgorithm` - The algorithm to use for verification (default is `'HS256'`). + +**Returns:** + +- `Promise` - The decoded payload if the token is valid. + +### `decode` + +Decodes a JWT without verifying its signature. + +**Parameters:** + +- `token: string` - The JWT to decode. + +**Returns:** + +- `{ header: TokenHeader; payload: JWTPayload }` - The decoded header and payload. + +## Types + +### `JWTPayload` + +Defines the structure of the JWT payload. + +```typescript +type JWTPayload = { + [key: string]: unknown; + exp?: number; + nbf?: number; + iat?: number; +}; +``` + +### `TokenHeader` + +Defines the structure of the JWT header. + +```typescript +interface TokenHeader { + alg: SignatureAlgorithm; + typ?: 'JWT'; +} +``` + +## Errors + +### `JwtAlgorithmNotImplemented` + +Thrown when an algorithm is not implemented. + +### `JwtTokenInvalid` + +Thrown when a JWT is invalid. + +### `JwtTokenNotBefore` + +Thrown when a JWT is used before its `nbf` claim. + +### `JwtTokenExpired` + +Thrown when a JWT has expired. + +### `JwtTokenIssuedAt` + +Thrown when a JWT `iat` claim is in the future. + +### `JwtHeaderInvalid` + +Thrown when a JWT header is invalid. + +### `JwtTokenSignatureMismatched` + +Thrown when a JWT signature does not match. + +## Contributing + +Feel free to submit issues or pull requests to improve the functionality or documentation. diff --git a/packages/jwt/jest.config.ts b/packages/jwt/jest.config.ts new file mode 100644 index 0000000..d197bf5 --- /dev/null +++ b/packages/jwt/jest.config.ts @@ -0,0 +1,22 @@ +/** + * For a detailed explanation regarding each configuration property, visit: + * https://jestjs.io/docs/configuration + */ + +import type { Config } from 'jest'; + +const config: Config = { + clearMocks: true, + coverageProvider: 'v8', + preset: 'ts-jest', + testEnvironment: 'node', + testMatch: ['**/?(*.)+(spec|test).[tj]s?(x)'], + testPathIgnorePatterns: ['/node_modules/'], + transform: { + '^.+\\.ts$': 'ts-jest', + }, + transformIgnorePatterns: ['/node_modules/'], + setupFilesAfterEnv: ['./jest.setup.ts'], +}; + +export default config; diff --git a/packages/jwt/jest.setup.ts b/packages/jwt/jest.setup.ts new file mode 100644 index 0000000..acb63d8 --- /dev/null +++ b/packages/jwt/jest.setup.ts @@ -0,0 +1,4 @@ +import { Crypto, CryptoKey } from '@peculiar/webcrypto'; + +globalThis.crypto = new Crypto(); +globalThis.CryptoKey = CryptoKey; diff --git a/packages/jwt/package.json b/packages/jwt/package.json new file mode 100644 index 0000000..015ac35 --- /dev/null +++ b/packages/jwt/package.json @@ -0,0 +1,38 @@ +{ + "name": "@lib/jwt", + "version": "1.0.0", + "description": "", + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "scripts": { + "compile": "tsup --config ../../tsup.config.json", + "lint": "eslint .", + "lint:fix": "eslint --fix .", + "prettier": "prettier --write .", + "prettier:check": "prettier --check .", + "test": "jest" + }, + "types": "./dist/index.d.ts", + "exports": { + ".": { + "require": "./dist/index.js", + "import": "./dist/index.mjs", + "types": "./dist/index.d.ts" + } + }, + "author": "aziontech", + "license": "MIT", + "files": [ + "dist", + "package.json" + ], + "devDependencies": { + "@jest/globals": "^29.7.0", + "@peculiar/webcrypto": "^1.5.0", + "@types/jest": "^29.5.12", + "jest": "^29.7.0", + "ts-jest": "^29.2.2", + "ts-node": "^10.9.2", + "typescript": "^5.5.3" + } +} diff --git a/packages/jwt/src/common/types.ts b/packages/jwt/src/common/types.ts new file mode 100644 index 0000000..c2ff3b8 --- /dev/null +++ b/packages/jwt/src/common/types.ts @@ -0,0 +1,83 @@ +/** + * @module + * Type definitions for JWT utilities. + */ + +export class JwtAlgorithmNotImplemented extends Error { + constructor(alg: string) { + super(`${alg} is not an implemented algorithm`); + this.name = 'JwtAlgorithmNotImplemented'; + } +} + +export class JwtTokenInvalid extends Error { + constructor(token: string) { + super(`invalid JWT token: ${token}`); + this.name = 'JwtTokenInvalid'; + } +} + +export class JwtTokenNotBefore extends Error { + constructor(token: string) { + super(`token (${token}) is being used before it's valid`); + this.name = 'JwtTokenNotBefore'; + } +} + +export class JwtTokenExpired extends Error { + constructor(token: string) { + super(`token (${token}) expired`); + this.name = 'JwtTokenExpired'; + } +} + +export class JwtTokenIssuedAt extends Error { + constructor(currentTimestamp: number, iat: number) { + super(`Incorrect "iat" claim must be a older than "${currentTimestamp}" (iat: "${iat}")`); + this.name = 'JwtTokenIssuedAt'; + } +} + +export class JwtHeaderInvalid extends Error { + constructor(header: object) { + super(`jwt header is invalid: ${JSON.stringify(header)}`); + this.name = 'JwtHeaderInvalid'; + } +} + +export class JwtTokenSignatureMismatched extends Error { + constructor(token: string) { + super(`token(${token}) signature mismatched`); + this.name = 'JwtTokenSignatureMismatched'; + } +} + +export enum CryptoKeyUsage { + Encrypt = 'encrypt', + Decrypt = 'decrypt', + Sign = 'sign', + Verify = 'verify', + DeriveKey = 'deriveKey', + DeriveBits = 'deriveBits', + WrapKey = 'wrapKey', + UnwrapKey = 'unwrapKey', +} + +/** + * JWT Payload + */ +export type JWTPayload = { + [key: string]: unknown; + /** + * The token is checked to ensure it has not expired. + */ + exp?: number; + /** + * The token is checked to ensure it is not being used before a specified time. + */ + nbf?: number; + /** + * The token is checked to ensure it is not issued in the future. + */ + iat?: number; +}; diff --git a/packages/jwt/src/index.ts b/packages/jwt/src/index.ts new file mode 100644 index 0000000..3ffbf17 --- /dev/null +++ b/packages/jwt/src/index.ts @@ -0,0 +1,18 @@ +/* + * Copyright Azion + * Licensed under the MIT license. See LICENSE file for details. + * + * Portions of this file Copyright Yusuke Wada and Hono contributors, + * licensed under the MIT license. See LICENSE file for details. + * + * Module based on hono jwt: + * https://github.com/honojs/hono/tree/main/src/utils/jwt + */ + +import { decode, sign, verify } from './jwt'; + +const jwt = { decode, sign, verify }; + +export { decode, sign, verify }; + +export default jwt; diff --git a/packages/jwt/src/jwa/index.ts b/packages/jwt/src/jwa/index.ts new file mode 100644 index 0000000..47dbdb8 --- /dev/null +++ b/packages/jwt/src/jwa/index.ts @@ -0,0 +1,23 @@ +/** + * @module + * JSON Web Algorithms (JWA) + * https://datatracker.ietf.org/doc/html/rfc7518 + */ + +export enum AlgorithmTypes { + HS256 = 'HS256', + HS384 = 'HS384', + HS512 = 'HS512', + RS256 = 'RS256', + RS384 = 'RS384', + RS512 = 'RS512', + PS256 = 'PS256', + PS384 = 'PS384', + PS512 = 'PS512', + ES256 = 'ES256', + ES384 = 'ES384', + ES512 = 'ES512', + EdDSA = 'EdDSA', +} + +export type SignatureAlgorithm = keyof typeof AlgorithmTypes; diff --git a/packages/jwt/src/jwa/jwa.test.ts b/packages/jwt/src/jwa/jwa.test.ts new file mode 100644 index 0000000..22cd316 --- /dev/null +++ b/packages/jwt/src/jwa/jwa.test.ts @@ -0,0 +1,17 @@ +import { AlgorithmTypes } from './index'; + +describe('Types', () => { + it('AlgorithmTypes', () => { + expect('HS256' as AlgorithmTypes).toBe(AlgorithmTypes.HS256); + expect('HS384' as AlgorithmTypes).toBe(AlgorithmTypes.HS384); + expect('HS512' as AlgorithmTypes).toBe(AlgorithmTypes.HS512); + expect('RS256' as AlgorithmTypes).toBe(AlgorithmTypes.RS256); + expect('RS384' as AlgorithmTypes).toBe(AlgorithmTypes.RS384); + expect('RS512' as AlgorithmTypes).toBe(AlgorithmTypes.RS512); + + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + expect(undefined as AlgorithmTypes).toBe(undefined); + expect('' as AlgorithmTypes).toBe(''); + }); +}); diff --git a/packages/jwt/src/jws/index.ts b/packages/jwt/src/jws/index.ts new file mode 100644 index 0000000..4f73890 --- /dev/null +++ b/packages/jwt/src/jws/index.ts @@ -0,0 +1,217 @@ +/** + * @module + * JSON Web Signature (JWS) + * https://datatracker.ietf.org/doc/html/rfc7515 + */ + +import { CryptoKeyUsage, JwtAlgorithmNotImplemented } from '../common/types'; +import type { SignatureAlgorithm } from '../jwa'; +import { decodeBase64 } from '../utils/encode'; +import { utf8Encoder } from '../utils/utf8'; + +type KeyImporterAlgorithm = Parameters[2]; +type KeyAlgorithm = + | AlgorithmIdentifier + | RsaHashedImportParams + | (RsaPssParams & RsaHashedImportParams) + | (EcdsaParams & EcKeyImportParams) + | HmacImportParams; + +export type SignatureKey = string | JsonWebKey | CryptoKey; + +export async function signing( + privateKey: SignatureKey, + alg: SignatureAlgorithm, + data: BufferSource, +): Promise { + const algorithm = getKeyAlgorithm(alg); + const cryptoKey = await importPrivateKey(privateKey, algorithm); + return await crypto.subtle.sign(algorithm, cryptoKey, data); +} + +export async function verifying( + publicKey: SignatureKey, + alg: SignatureAlgorithm, + signature: BufferSource, + data: BufferSource, +): Promise { + const algorithm = getKeyAlgorithm(alg); + const cryptoKey = await importPublicKey(publicKey, algorithm); + return await crypto.subtle.verify(algorithm, cryptoKey, signature, data); +} + +export function pemToBinary(pem: string): Uint8Array { + return decodeBase64(pem.replace(/-+(BEGIN|END).*/g, '').replace(/\s/g, '')); +} + +export async function importPrivateKey(key: SignatureKey, alg: KeyImporterAlgorithm): Promise { + if (!crypto.subtle || !crypto.subtle.importKey) { + throw new Error('`crypto.subtle.importKey` is undefined. JWT auth middleware requires it.'); + } + if (isCryptoKey(key)) { + if (key.type !== 'private') { + throw new Error(`unexpected non private key: CryptoKey.type is ${key.type}`); + } + return key; + } + const usages = [CryptoKeyUsage.Sign]; + if (typeof key === 'object') { + // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey#json_web_key_import + return await crypto.subtle.importKey('jwk', key, alg, false, usages); + } + if (key.includes('PRIVATE')) { + // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey#pkcs_8_import + return await crypto.subtle.importKey('pkcs8', pemToBinary(key), alg, false, usages); + } + return await crypto.subtle.importKey('raw', utf8Encoder.encode(key), alg, false, usages); +} + +export async function importPublicKey(key: SignatureKey, alg: KeyImporterAlgorithm): Promise { + if (!crypto.subtle || !crypto.subtle.importKey) { + throw new Error('`crypto.subtle.importKey` is undefined. JWT auth middleware requires it.'); + } + if (isCryptoKey(key)) { + if (key.type === 'public' || key.type === 'secret') { + return key; + } + key = await exportPublicJwkFrom(key); + } + if (typeof key === 'string' && key.includes('PRIVATE')) { + // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey#pkcs_8_import + const privateKey = await crypto.subtle.importKey('pkcs8', pemToBinary(key), alg, true, [CryptoKeyUsage.Sign]); + key = await exportPublicJwkFrom(privateKey); + } + const usages = [CryptoKeyUsage.Verify]; + if (typeof key === 'object') { + // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey#json_web_key_import + return await crypto.subtle.importKey('jwk', key, alg, false, usages); + } + if (key.includes('PUBLIC')) { + // https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/importKey#subjectpublickeyinfo_import + return await crypto.subtle.importKey('spki', pemToBinary(key), alg, false, usages); + } + return await crypto.subtle.importKey('raw', utf8Encoder.encode(key), alg, false, usages); +} + +// https://datatracker.ietf.org/doc/html/rfc7517 +export async function exportPublicJwkFrom(privateKey: CryptoKey): Promise { + if (privateKey.type !== 'private') { + throw new Error(`unexpected key type: ${privateKey.type}`); + } + if (!privateKey.extractable) { + throw new Error('unexpected private key is unextractable'); + } + const jwk = await crypto.subtle.exportKey('jwk', privateKey); + const { kty } = jwk; // common + const { alg, e, n } = jwk; // rsa + const { crv, x, y } = jwk; // elliptic-curve + return { kty, alg, e, n, crv, x, y, key_ops: [CryptoKeyUsage.Verify] }; +} + +export function getKeyAlgorithm(name: SignatureAlgorithm): KeyAlgorithm { + switch (name) { + case 'HS256': + return { + name: 'HMAC', + hash: { + name: 'SHA-256', + }, + } satisfies HmacImportParams; + case 'HS384': + return { + name: 'HMAC', + hash: { + name: 'SHA-384', + }, + } satisfies HmacImportParams; + case 'HS512': + return { + name: 'HMAC', + hash: { + name: 'SHA-512', + }, + } satisfies HmacImportParams; + case 'RS256': + return { + name: 'RSASSA-PKCS1-v1_5', + hash: { + name: 'SHA-256', + }, + } satisfies RsaHashedImportParams; + case 'RS384': + return { + name: 'RSASSA-PKCS1-v1_5', + hash: { + name: 'SHA-384', + }, + } satisfies RsaHashedImportParams; + case 'RS512': + return { + name: 'RSASSA-PKCS1-v1_5', + hash: { + name: 'SHA-512', + }, + } satisfies RsaHashedImportParams; + case 'PS256': + return { + name: 'RSA-PSS', + hash: { + name: 'SHA-256', + }, + saltLength: 32, // 256 >> 3 + } satisfies RsaPssParams & RsaHashedImportParams; + case 'PS384': + return { + name: 'RSA-PSS', + hash: { + name: 'SHA-384', + }, + saltLength: 48, // 384 >> 3 + } satisfies RsaPssParams & RsaHashedImportParams; + case 'PS512': + return { + name: 'RSA-PSS', + hash: { + name: 'SHA-512', + }, + saltLength: 64, // 512 >> 3, + } satisfies RsaPssParams & RsaHashedImportParams; + case 'ES256': + return { + name: 'ECDSA', + hash: { + name: 'SHA-256', + }, + namedCurve: 'P-256', + } satisfies EcdsaParams & EcKeyImportParams; + case 'ES384': + return { + name: 'ECDSA', + hash: { + name: 'SHA-384', + }, + namedCurve: 'P-384', + } satisfies EcdsaParams & EcKeyImportParams; + case 'ES512': + return { + name: 'ECDSA', + hash: { + name: 'SHA-512', + }, + namedCurve: 'P-521', + } satisfies EcdsaParams & EcKeyImportParams; + case 'EdDSA': + // Currently, supported only Safari and Deno, Node.js. + // See: https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/verify + return { + name: 'Ed25519', + namedCurve: 'Ed25519', + }; + default: + throw new JwtAlgorithmNotImplemented(name); + } +} + +export function isCryptoKey(key: SignatureKey): key is CryptoKey { + return key instanceof CryptoKey; +} diff --git a/packages/jwt/src/jws/jws.test.ts b/packages/jwt/src/jws/jws.test.ts new file mode 100644 index 0000000..06abeb6 --- /dev/null +++ b/packages/jwt/src/jws/jws.test.ts @@ -0,0 +1,148 @@ +/* eslint-disable @typescript-eslint/no-explicit-any */ +import { JwtAlgorithmNotImplemented } from '../common/types'; +import { getKeyAlgorithm, pemToBinary, signing, verifying } from './index'; + +describe('JWS module', () => { + describe('signing', () => { + it('should sign data with a private key (string)', async () => { + const privateKey = 'my-private-key'; + const alg = 'HS256'; + const data = new Uint8Array([1, 2, 3]); + + const subtleSignSpy = jest.spyOn(crypto.subtle, 'sign'); + + await signing(privateKey, alg, data); + + expect(subtleSignSpy).toHaveBeenCalledTimes(1); + expect(subtleSignSpy).toHaveBeenCalledWith(getKeyAlgorithm(alg), expect.any(CryptoKey), data); + + subtleSignSpy.mockRestore(); + }); + + it('should sign data with a private key (JsonWebKey)', async () => { + const privateKey: JsonWebKey = { kty: 'oct', k: 'some_key' }; + const alg = 'HS256'; + const data = new Uint8Array([1, 2, 3]); + + const subtleSignSpy = jest.spyOn(crypto.subtle, 'sign'); + + await signing(privateKey, alg, data); + + expect(subtleSignSpy).toHaveBeenCalledTimes(1); + expect(subtleSignSpy).toHaveBeenCalledWith(getKeyAlgorithm(alg), expect.any(CryptoKey), data); + + subtleSignSpy.mockRestore(); + }); + + it('should throw an error for unsupported algorithms', async () => { + const privateKey = 'my-private-key'; + const alg = 'UNSUPPORTED' as any; + const data = new Uint8Array([1, 2, 3]); + + await expect(signing(privateKey, alg, data)).rejects.toThrow(JwtAlgorithmNotImplemented); + }); + }); + + describe('verifying', () => { + it('should verify data with a public key', async () => { + const publicKey = 'my-public-key'; + const alg = 'HS256'; + const signature = new Uint8Array([1, 2, 3]); + const data = new Uint8Array([4, 5, 6]); + + const subtleVerifySpy = jest.spyOn(crypto.subtle, 'verify').mockResolvedValue(true); + + const result = await verifying(publicKey, alg, signature, data); + + expect(subtleVerifySpy).toHaveBeenCalledTimes(1); + expect(subtleVerifySpy).toHaveBeenCalledWith(getKeyAlgorithm(alg), expect.any(CryptoKey), signature, data); + expect(result).toBe(true); + + subtleVerifySpy.mockRestore(); + }); + }); + + describe('pemToBinary', () => { + it('should convert PEM to binary', () => { + const pem = '-----BEGIN PRIVATE KEY-----some_base64_data-----END PRIVATE KEY-----'; + const binary = pemToBinary(pem); + + expect(binary).toBeInstanceOf(Uint8Array); + }); + }); + + describe('getKeyAlgorithm', () => { + it('should return the correct algorithm for supported algorithms', async () => { + expect(getKeyAlgorithm('HS256')).toEqual({ + name: 'HMAC', + hash: { name: 'SHA-256' }, + }); + expect(getKeyAlgorithm('HS384')).toEqual({ + name: 'HMAC', + hash: { name: 'SHA-384' }, + }); + expect(getKeyAlgorithm('HS512')).toEqual({ + name: 'HMAC', + hash: { name: 'SHA-512' }, + }); + expect(getKeyAlgorithm('RS256')).toEqual({ + name: 'RSASSA-PKCS1-v1_5', + hash: { name: 'SHA-256' }, + }); + expect(getKeyAlgorithm('RS384')).toEqual({ + name: 'RSASSA-PKCS1-v1_5', + hash: { name: 'SHA-384' }, + }); + expect(getKeyAlgorithm('RS512')).toEqual({ + name: 'RSASSA-PKCS1-v1_5', + hash: { name: 'SHA-512' }, + }); + expect(getKeyAlgorithm('PS256')).toEqual({ + name: 'RSA-PSS', + hash: { name: 'SHA-256' }, + saltLength: 32, + }); + expect(getKeyAlgorithm('PS384')).toEqual({ + name: 'RSA-PSS', + hash: { + name: 'SHA-384', + }, + saltLength: 48, + }); + expect(getKeyAlgorithm('PS512')).toEqual({ + name: 'RSA-PSS', + hash: { + name: 'SHA-512', + }, + saltLength: 64, + }); + expect(getKeyAlgorithm('ES256')).toEqual({ + name: 'ECDSA', + hash: { + name: 'SHA-256', + }, + namedCurve: 'P-256', + }); + expect(getKeyAlgorithm('ES384')).toEqual({ + name: 'ECDSA', + hash: { + name: 'SHA-384', + }, + namedCurve: 'P-384', + }); + expect(getKeyAlgorithm('ES512')).toEqual({ + name: 'ECDSA', + hash: { + name: 'SHA-512', + }, + namedCurve: 'P-521', + }); + expect(getKeyAlgorithm('EdDSA')).toEqual({ + name: 'Ed25519', + namedCurve: 'Ed25519', + }); + + expect(() => getKeyAlgorithm('UNSUPPORTED' as any)).toThrow(JwtAlgorithmNotImplemented); + }); + }); +}); diff --git a/packages/jwt/src/jwt/index.ts b/packages/jwt/src/jwt/index.ts new file mode 100644 index 0000000..afa0b1e --- /dev/null +++ b/packages/jwt/src/jwt/index.ts @@ -0,0 +1,109 @@ +/** + * @module + * JSON Web Token (JWT) + * https://datatracker.ietf.org/doc/html/rfc7519 + */ + +import type { JWTPayload } from '../common/types'; +import { + JwtHeaderInvalid, + JwtTokenExpired, + JwtTokenInvalid, + JwtTokenIssuedAt, + JwtTokenNotBefore, + JwtTokenSignatureMismatched, +} from '../common/types'; +import type { SignatureAlgorithm } from '../jwa'; +import { AlgorithmTypes } from '../jwa'; +import type { SignatureKey } from '../jws'; +import { signing, verifying } from '../jws'; +import { decodeBase64Url, encodeBase64Url } from '../utils/encode'; +import { utf8Decoder, utf8Encoder } from '../utils/utf8'; + +const encodeJwtPart = (part: unknown): string => + encodeBase64Url(utf8Encoder.encode(JSON.stringify(part))).replace(/=/g, ''); +const encodeSignaturePart = (buf: ArrayBufferLike): string => encodeBase64Url(buf).replace(/=/g, ''); + +const decodeJwtPart = (part: string): TokenHeader | JWTPayload | undefined => + JSON.parse(utf8Decoder.decode(decodeBase64Url(part))); + +export interface TokenHeader { + alg: SignatureAlgorithm; + typ?: 'JWT'; +} + +export function isTokenHeader(obj: unknown): obj is TokenHeader { + if (typeof obj === 'object' && obj !== null) { + const objWithAlg = obj as { [key: string]: unknown }; + return ( + 'alg' in objWithAlg && + Object.values(AlgorithmTypes).includes(objWithAlg.alg as AlgorithmTypes) && + (!('typ' in objWithAlg) || objWithAlg.typ === 'JWT') + ); + } + return false; +} + +export const sign = async ( + payload: JWTPayload, + privateKey: SignatureKey, + alg: SignatureAlgorithm = 'HS256', +): Promise => { + const encodedPayload = encodeJwtPart(payload); + const encodedHeader = encodeJwtPart({ alg, typ: 'JWT' } satisfies TokenHeader); + + const partialToken = `${encodedHeader}.${encodedPayload}`; + + const signaturePart = await signing(privateKey, alg, utf8Encoder.encode(partialToken)); + const signature = encodeSignaturePart(signaturePart); + + return `${partialToken}.${signature}`; +}; + +export const verify = async ( + token: string, + publicKey: SignatureKey, + alg: SignatureAlgorithm = 'HS256', +): Promise => { + const tokenParts = token.split('.'); + if (tokenParts.length !== 3) { + throw new JwtTokenInvalid(token); + } + + const { header, payload } = decode(token); + if (!isTokenHeader(header)) { + throw new JwtHeaderInvalid(header); + } + const now = Math.floor(Date.now() / 1000); + if (payload.nbf && payload.nbf > now) { + throw new JwtTokenNotBefore(token); + } + if (payload.exp && payload.exp <= now) { + throw new JwtTokenExpired(token); + } + if (payload.iat && now < payload.iat) { + throw new JwtTokenIssuedAt(now, payload.iat); + } + + const headerPayload = token.substring(0, token.lastIndexOf('.')); + const verified = await verifying(publicKey, alg, decodeBase64Url(tokenParts[2]), utf8Encoder.encode(headerPayload)); + if (!verified) { + throw new JwtTokenSignatureMismatched(token); + } + + return payload; +}; + +export const decode = (token: string): { header: TokenHeader; payload: JWTPayload } => { + try { + const [h, p] = token.split('.'); + const header = decodeJwtPart(h) as TokenHeader; + const payload = decodeJwtPart(p) as JWTPayload; + return { + header, + payload, + }; + } catch (e) { + throw new JwtTokenInvalid(token); + } +}; diff --git a/packages/jwt/src/jwt/jwt.test.ts b/packages/jwt/src/jwt/jwt.test.ts new file mode 100644 index 0000000..ebad734 --- /dev/null +++ b/packages/jwt/src/jwt/jwt.test.ts @@ -0,0 +1,497 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import { + JwtAlgorithmNotImplemented, + JwtTokenExpired, + JwtTokenInvalid, + JwtTokenIssuedAt, + JwtTokenNotBefore, + JwtTokenSignatureMismatched, +} from '../common/types'; +import { AlgorithmTypes } from '../jwa'; +import { encodeBase64 } from '../utils/encode'; +import * as JWT from './index'; + +describe('isTokenHeader', () => { + it('should return true for valid TokenHeader', () => { + const validTokenHeader: JWT.TokenHeader = { + alg: AlgorithmTypes.HS256, + typ: 'JWT', + }; + + expect(JWT.isTokenHeader(validTokenHeader)).toBe(true); + }); + + it('should return false for invalid TokenHeader', () => { + const invalidTokenHeader = { + alg: 'invalid', + typ: 'JWT', + }; + + expect(JWT.isTokenHeader(invalidTokenHeader)).toBe(false); + }); + + it('returns true even if the typ field is absent in a TokenHeader', () => { + const validTokenHeader: JWT.TokenHeader = { + alg: AlgorithmTypes.HS256, + }; + + expect(JWT.isTokenHeader(validTokenHeader)).toBe(true); + }); + + it('returns false when the typ field is present but empty', () => { + const invalidTokenHeader = { + alg: AlgorithmTypes.HS256, + typ: '', + }; + + expect(JWT.isTokenHeader(invalidTokenHeader)).toBe(false); + }); +}); + +describe('JWT', () => { + it('JwtAlgorithmNotImplemented', async () => { + const payload = { message: 'hello world' }; + const secret = 'a-secret'; + const alg = ''; + let tok = ''; + let err: JwtAlgorithmNotImplemented; + try { + tok = await JWT.sign(payload, secret, alg as AlgorithmTypes); + } catch (e) { + err = e as JwtAlgorithmNotImplemented; + } + expect(tok).toBe(''); + // @ts-ignore + expect(err).toEqual(new JwtAlgorithmNotImplemented(alg)); + }); + + it('JwtTokenInvalid', async () => { + const tok = 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXNzYWdlIjoiaGVsbG8gd29ybGQifQ'; + const secret = 'a-secret'; + let err: JwtTokenInvalid; + let authorized; + try { + authorized = await JWT.verify(tok, secret, AlgorithmTypes.HS256); + } catch (e) { + err = e as JwtTokenInvalid; + } + // @ts-ignore + expect(err).toEqual(new JwtTokenInvalid(tok)); + expect(authorized).toBeUndefined(); + }); + + it('JwtTokenNotBefore', async () => { + const tok = + 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2NjQ2MDYzMzQsImV4cCI6MTY2NDYwOTkzNCwibmJmIjoiMzEwNDYwNjI2NCJ9.hpSDT_cfkxeiLWEpWVT8TDxFP3dFi27q1K7CcMcLXHc'; + const secret = 'a-secret'; + let err: JwtTokenNotBefore; + let authorized; + try { + authorized = await JWT.verify(tok, secret, AlgorithmTypes.HS256); + } catch (e) { + err = e as JwtTokenNotBefore; + } + // @ts-ignore + expect(err).toEqual(new JwtTokenNotBefore(tok)); + expect(authorized).toBeUndefined(); + }); + + it('JwtTokenExpired', async () => { + const tok = + 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE2MzMwNDYxMDAsImV4cCI6MTYzMzA0NjQwMH0.H-OI1TWAbmK8RonvcpPaQcNvOKS9sxinEOsgKwjoiVo'; + const secret = 'a-secret'; + let err; + let authorized; + try { + authorized = await JWT.verify(tok, secret, AlgorithmTypes.HS256); + } catch (e) { + err = e; + } + expect(err).toEqual(new JwtTokenExpired(tok)); + expect(authorized).toBeUndefined(); + }); + + it('JwtTokenIssuedAt', async () => { + const now = 1633046400; + jest.useFakeTimers(); + jest.setSystemTime(new Date(now * 1000)); + + const iat = now + 1000; // after 1s + const payload = { role: 'api_role', iat }; + const secret = 'a-secret'; + const tok = await JWT.sign(payload, secret, AlgorithmTypes.HS256); + + let err; + let authorized; + try { + authorized = await JWT.verify(tok, secret, AlgorithmTypes.HS256); + } catch (e) { + err = e; + } + expect(err).toEqual(new JwtTokenIssuedAt(now, iat)); + expect(authorized).toBeUndefined(); + }); + + it('HS256 sign & verify & decode', async () => { + const payload = { message: 'hello world' }; + const secret = 'a-secret'; + const tok = await JWT.sign(payload, secret, AlgorithmTypes.HS256); + const expected = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXNzYWdlIjoiaGVsbG8gd29ybGQifQ.B54pAqIiLbu170tGQ1rY06Twv__0qSHTA0ioQPIOvFE'; + expect(tok).toEqual(expected); + + const verifiedPayload = await JWT.verify(tok, secret, AlgorithmTypes.HS256); + expect(verifiedPayload).not.toBeUndefined(); + expect(verifiedPayload).toEqual(payload); + + expect(JWT.decode(tok)).toEqual({ + header: { + alg: 'HS256', + typ: 'JWT', + }, + payload: { + message: 'hello world', + }, + }); + }); + + it('HS256 sign & verify', async () => { + const payload = { message: 'hello world' }; + const secret = 'a-secret'; + const tok = await JWT.sign(payload, secret, AlgorithmTypes.HS256); + const expected = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXNzYWdlIjoiaGVsbG8gd29ybGQifQ.B54pAqIiLbu170tGQ1rY06Twv__0qSHTA0ioQPIOvFE'; + expect(tok).toEqual(expected); + + let err = null; + let authorized; + try { + authorized = await JWT.verify(tok, secret + 'invalid', AlgorithmTypes.HS256); + } catch (e) { + err = e; + } + expect(authorized).toBeUndefined(); + expect(err instanceof JwtTokenSignatureMismatched).toBe(true); + }); + + it('HS512 sign & verify & decode', async () => { + const payload = { message: 'hello world' }; + const secret = 'a-secret'; + const tok = await JWT.sign(payload, secret, AlgorithmTypes.HS512); + const expected = + 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJtZXNzYWdlIjoiaGVsbG8gd29ybGQifQ.RqVLgExB_GXF1-9T-k4V4HjFmiuQKTEjVSiZd-YL0WERIlywZ7PfzAuTZSJU4gg8cscGamQa030cieEWrYcywg'; + expect(tok).toEqual(expected); + + const verifiedPayload = await JWT.verify(tok, secret, AlgorithmTypes.HS512); + expect(verifiedPayload).not.toBeUndefined(); + expect(verifiedPayload).toEqual(payload); + + expect(JWT.decode(tok)).toEqual({ + header: { + alg: 'HS512', + typ: 'JWT', + }, + payload: { + message: 'hello world', + }, + }); + }); + + it('HS512 sign & verify', async () => { + const payload = { message: 'hello world' }; + const secret = 'a-secret'; + const tok = await JWT.sign(payload, secret, AlgorithmTypes.HS512); + const expected = + 'eyJhbGciOiJIUzUxMiIsInR5cCI6IkpXVCJ9.eyJtZXNzYWdlIjoiaGVsbG8gd29ybGQifQ.RqVLgExB_GXF1-9T-k4V4HjFmiuQKTEjVSiZd-YL0WERIlywZ7PfzAuTZSJU4gg8cscGamQa030cieEWrYcywg'; + expect(tok).toEqual(expected); + + let err = null; + let authorized; + try { + authorized = await JWT.verify(tok, secret + 'invalid', AlgorithmTypes.HS256); + } catch (e) { + err = e; + } + expect(authorized).toBeUndefined(); + expect(err instanceof JwtTokenSignatureMismatched).toBe(true); + }); + + it('HS384 sign & verify', async () => { + const payload = { message: 'hello world' }; + const secret = 'a-secret%你好'; + const tok = await JWT.sign(payload, secret, AlgorithmTypes.HS384); + const expected = + 'eyJhbGciOiJIUzM4NCIsInR5cCI6IkpXVCJ9.eyJtZXNzYWdlIjoiaGVsbG8gd29ybGQifQ.C1Br1183Oy6O7th4NDCOaI9WB75i3FMCuYlv1tCL9HggsU89T-SNutghwhJykD3r'; + expect(tok).toEqual(expected); + + let err = null; + let authorized; + try { + authorized = await JWT.verify(tok, secret + 'invalid', AlgorithmTypes.HS256); + } catch (e) { + err = e; + } + expect(authorized).toBeUndefined(); + expect(err instanceof JwtTokenSignatureMismatched).toBe(true); + }); + + const rsTestCases = [ + { + alg: AlgorithmTypes.RS256, + hash: 'SHA-256', + }, + { + alg: AlgorithmTypes.RS384, + hash: 'SHA-384', + }, + { + alg: AlgorithmTypes.RS512, + hash: 'SHA-512', + }, + ]; + for (const tc of rsTestCases) { + it(`${tc.alg} sign & verify`, async () => { + const alg = tc.alg; + const payload = { message: 'hello world' }; + const keyPair = await generateRSAKey(tc.hash); + const pemPrivateKey = await exportPEMPrivateKey(keyPair.privateKey); + const pemPublicKey = await exportPEMPublicKey(keyPair.publicKey); + const jwkPublicKey = await exportJWK(keyPair.publicKey); + + const tok = await JWT.sign(payload, pemPrivateKey, alg); + expect(await JWT.verify(tok, pemPublicKey, alg)).toEqual(payload); + expect(await JWT.verify(tok, pemPrivateKey, alg)).toEqual(payload); + expect(await JWT.verify(tok, jwkPublicKey, alg)).toEqual(payload); + + const keyPair2 = await generateRSAKey(tc.hash); + const unexpectedPemPublicKey = await exportPEMPublicKey(keyPair2.publicKey); + + let err = null; + let authorized; + try { + authorized = await JWT.verify(tok, unexpectedPemPublicKey, alg); + } catch (e) { + err = e; + } + expect(authorized).toBeUndefined(); + expect(err instanceof JwtTokenSignatureMismatched).toBe(true); + }); + + it(`${tc.alg} sign & verify w/ CryptoKey`, async () => { + const alg = tc.alg; + const payload = { message: 'hello world' }; + const keyPair = await generateRSAKey(tc.hash); + + const tok = await JWT.sign(payload, keyPair.privateKey, alg); + expect(await JWT.verify(tok, keyPair.privateKey, alg)).toEqual(payload); + expect(await JWT.verify(tok, keyPair.publicKey, alg)).toEqual(payload); + }); + } + + const psTestCases = [ + { + alg: AlgorithmTypes.PS256, + hash: 'SHA-256', + }, + { + alg: AlgorithmTypes.PS384, + hash: 'SHA-384', + }, + { + alg: AlgorithmTypes.PS512, + hash: 'SHA-512', + }, + ]; + for (const tc of psTestCases) { + it(`${tc.alg} sign & verify`, async () => { + const alg = tc.alg; + const payload = { message: 'hello world' }; + const keyPair = await generateRSAPSSKey(tc.hash); + const pemPrivateKey = await exportPEMPrivateKey(keyPair.privateKey); + const pemPublicKey = await exportPEMPublicKey(keyPair.publicKey); + const jwkPublicKey = await exportJWK(keyPair.publicKey); + + const tok = await JWT.sign(payload, pemPrivateKey, alg); + expect(await JWT.verify(tok, pemPublicKey, alg)).toEqual(payload); + expect(await JWT.verify(tok, pemPrivateKey, alg)).toEqual(payload); + expect(await JWT.verify(tok, jwkPublicKey, alg)).toEqual(payload); + + const keyPair2 = await generateRSAPSSKey(tc.hash); + const unexpectedPemPublicKey = await exportPEMPublicKey(keyPair2.publicKey); + + let err = null; + let authorized; + try { + authorized = await JWT.verify(tok, unexpectedPemPublicKey, alg); + } catch (e) { + err = e; + } + expect(authorized).toBeUndefined(); + expect(err instanceof JwtTokenSignatureMismatched).toBe(true); + }); + + it(`${tc.alg} sign & verify w/ CryptoKey`, async () => { + const alg = tc.alg; + const payload = { message: 'hello world' }; + const keyPair = await generateRSAPSSKey(tc.hash); + + const tok = await JWT.sign(payload, keyPair.privateKey, alg); + expect(await JWT.verify(tok, keyPair.privateKey, alg)).toEqual(payload); + expect(await JWT.verify(tok, keyPair.publicKey, alg)).toEqual(payload); + }); + } + + const esTestCases = [ + { + alg: AlgorithmTypes.ES256, + namedCurve: 'P-256', + }, + { + alg: AlgorithmTypes.ES384, + namedCurve: 'P-384', + }, + { + alg: AlgorithmTypes.ES512, + namedCurve: 'P-521', + }, + ]; + for (const tc of esTestCases) { + it(`${tc.alg} sign & verify`, async () => { + const alg = tc.alg; + const payload = { message: 'hello world' }; + const keyPair = await generateECDSAKey(tc.namedCurve); + const pemPrivateKey = await exportPEMPrivateKey(keyPair.privateKey); + const pemPublicKey = await exportPEMPublicKey(keyPair.publicKey); + const jwkPublicKey = await exportJWK(keyPair.publicKey); + + const tok = await JWT.sign(payload, pemPrivateKey, alg); + expect(await JWT.verify(tok, pemPublicKey, alg)).toEqual(payload); + expect(await JWT.verify(tok, pemPrivateKey, alg)).toEqual(payload); + expect(await JWT.verify(tok, jwkPublicKey, alg)).toEqual(payload); + + const keyPair2 = await generateECDSAKey(tc.namedCurve); + const unexpectedPemPublicKey = await exportPEMPublicKey(keyPair2.publicKey); + + let err = null; + let authorized; + try { + authorized = await JWT.verify(tok, unexpectedPemPublicKey, alg); + } catch (e) { + err = e; + } + expect(authorized).toBeUndefined(); + expect(err instanceof JwtTokenSignatureMismatched).toBe(true); + }); + + it(`${tc.alg} sign & verify w/ CryptoKey`, async () => { + const alg = tc.alg; + const payload = { message: 'hello world' }; + const keyPair = await generateECDSAKey(tc.namedCurve); + + const tok = await JWT.sign(payload, keyPair.privateKey, alg); + expect(await JWT.verify(tok, keyPair.privateKey, alg)).toEqual(payload); + expect(await JWT.verify(tok, keyPair.publicKey, alg)).toEqual(payload); + }); + } + + it('EdDSA sign & verify', async () => { + const alg = 'EdDSA'; + const payload = { message: 'hello world' }; + const keyPair = await generateEd25519Key(); + const pemPrivateKey = await exportPEMPrivateKey(keyPair.privateKey); + const pemPublicKey = await exportPEMPublicKey(keyPair.publicKey); + const jwkPublicKey = await exportJWK(keyPair.publicKey); + + const tok = await JWT.sign(payload, pemPrivateKey, alg); + expect(await JWT.verify(tok, pemPublicKey, alg)).toEqual(payload); + expect(await JWT.verify(tok, pemPrivateKey, alg)).toEqual(payload); + expect(await JWT.verify(tok, jwkPublicKey, alg)).toEqual(payload); + + const keyPair2 = await generateEd25519Key(); + const unexpectedPemPublicKey = await exportPEMPublicKey(keyPair2.publicKey); + + let err = null; + let authorized; + try { + authorized = await JWT.verify(tok, unexpectedPemPublicKey, alg); + } catch (e) { + err = e; + } + expect(authorized).toBeUndefined(); + expect(err instanceof JwtTokenSignatureMismatched).toBe(true); + }); + + it('EdDSA sign & verify w/ CryptoKey', async () => { + const alg = 'EdDSA'; + const payload = { message: 'hello world' }; + const keyPair = await generateEd25519Key(); + + const tok = await JWT.sign(payload, keyPair.privateKey, alg); + expect(await JWT.verify(tok, keyPair.privateKey, alg)).toEqual(payload); + expect(await JWT.verify(tok, keyPair.publicKey, alg)).toEqual(payload); + }); +}); + +async function exportPEMPrivateKey(key: CryptoKey): Promise { + const exported = await crypto.subtle.exportKey('pkcs8', key); + const pem = `-----BEGIN PRIVATE KEY-----\n${encodeBase64(exported)}\n-----END PRIVATE KEY-----`; + return pem; +} + +async function exportPEMPublicKey(key: CryptoKey): Promise { + const exported = await crypto.subtle.exportKey('spki', key); + const pem = `-----BEGIN PUBLIC KEY-----\n${encodeBase64(exported)}\n-----END PUBLIC KEY-----`; + return pem; +} + +async function exportJWK(key: CryptoKey): Promise { + return await crypto.subtle.exportKey('jwk', key); +} + +async function generateRSAKey(hash: string): Promise { + return await crypto.subtle.generateKey( + { + hash, + modulusLength: 2048, + publicExponent: new Uint8Array([1, 0, 1]), + name: 'RSASSA-PKCS1-v1_5', + }, + true, + ['sign', 'verify'], + ); +} + +async function generateRSAPSSKey(hash: string): Promise { + return await crypto.subtle.generateKey( + { + hash, + modulusLength: 2048, + publicExponent: new Uint8Array([1, 0, 1]), + name: 'RSA-PSS', + }, + true, + ['sign', 'verify'], + ); +} + +async function generateECDSAKey(namedCurve: string): Promise { + return await crypto.subtle.generateKey( + { + name: 'ECDSA', + namedCurve, + }, + true, + ['sign', 'verify'], + ); +} + +async function generateEd25519Key(): Promise { + return await crypto.subtle.generateKey( + { + name: 'Ed25519', + namedCurve: 'Ed25519', + }, + true, + ['sign', 'verify'], + ); +} diff --git a/packages/jwt/src/utils/encode/encode.test.ts b/packages/jwt/src/utils/encode/encode.test.ts new file mode 100644 index 0000000..5c439b8 --- /dev/null +++ b/packages/jwt/src/utils/encode/encode.test.ts @@ -0,0 +1,58 @@ +import { decodeBase64Url, encodeBase64Url } from './index'; + +const toURLBase64 = (base64String: string): string => + base64String.replace(/\+|\//g, (m) => ({ '+': '-', '/': '_' })[m] ?? m); + +const str2UInt8Array = (s: string): Uint8Array => { + const buffer = new Uint8Array(new ArrayBuffer(s.length)); + for (let i = 0, len = buffer.byteLength; i < len; i++) { + buffer[i] = s.charCodeAt(i); + } + return buffer; +}; + +describe('base64', () => { + const utf8Encoder = new TextEncoder(); + describe.each([ + // basic + [utf8Encoder.encode('Hello, 世界'), 'SGVsbG8sIOS4lueVjA=='], + [utf8Encoder.encode('炎'), '54KO'], + [utf8Encoder.encode('🔥'), '8J+UpQ=='], + [utf8Encoder.encode('http://github.com/honojs/hono'), 'aHR0cDovL2dpdGh1Yi5jb20vaG9ub2pzL2hvbm8='], + + // RFC 3548 examples + [str2UInt8Array('\x14\xfb\x9c\x03\xd9\x7e'), 'FPucA9l+'], + [str2UInt8Array('\x14\xfb\x9c\x03\xd9'), 'FPucA9k='], + [str2UInt8Array('\x14\xfb\x9c\x03'), 'FPucAw=='], + + // RFC 4648 examples + [str2UInt8Array(''), ''], + [str2UInt8Array('f'), 'Zg=='], + [str2UInt8Array('fo'), 'Zm8='], + [str2UInt8Array('foo'), 'Zm9v'], + [str2UInt8Array('foob'), 'Zm9vYg=='], + [str2UInt8Array('fooba'), 'Zm9vYmE='], + [str2UInt8Array('foobar'), 'Zm9vYmFy'], + + // Wikipedia examples + [str2UInt8Array('sure.'), 'c3VyZS4='], + [str2UInt8Array('sure'), 'c3VyZQ=='], + [str2UInt8Array('sur'), 'c3Vy'], + [str2UInt8Array('su'), 'c3U='], + [str2UInt8Array('leasure.'), 'bGVhc3VyZS4='], + [str2UInt8Array('easure.'), 'ZWFzdXJlLg=='], + [str2UInt8Array('asure.'), 'YXN1cmUu'], + [str2UInt8Array('sure.'), 'c3VyZS4='], + ])('stdDecoded: %s ; stdEncoded: %s', (stdDecoded, stdEncoded) => { + it('encode', () => { + const got = encodeBase64Url(stdDecoded); + const want = toURLBase64(stdEncoded); + expect(got).toStrictEqual(want); + }); + it('decode', () => { + const got = decodeBase64Url(toURLBase64(stdEncoded)); + const want = stdDecoded; + expect(got).toStrictEqual(want); + }); + }); +}); diff --git a/packages/jwt/src/utils/encode/index.ts b/packages/jwt/src/utils/encode/index.ts new file mode 100644 index 0000000..73fca5b --- /dev/null +++ b/packages/jwt/src/utils/encode/index.ts @@ -0,0 +1,34 @@ +/** + * @module + * Encode utility. + **/ + +export const decodeBase64Url = (str: string): Uint8Array => { + return decodeBase64(str.replace(/_|-/g, (m) => ({ _: '/', '-': '+' })[m] ?? m)); +}; + +export const encodeBase64Url = (buf: ArrayBufferLike): string => + encodeBase64(buf).replace(/\/|\+/g, (m) => ({ '/': '_', '+': '-' })[m] ?? m); + +// This approach is written in MDN. +// btoa does not support utf-8 characters. So we need a little bit hack. +export const encodeBase64 = (buf: ArrayBufferLike): string => { + let binary = ''; + const bytes = new Uint8Array(buf); + for (let i = 0, len = bytes.length; i < len; i++) { + binary += String.fromCharCode(bytes[i]); + } + return btoa(binary); +}; + +// atob does not support utf-8 characters. So we need a little bit hack. +export const decodeBase64 = (str: string): Uint8Array => { + const binary = atob(str); + const bytes = new Uint8Array(new ArrayBuffer(binary.length)); + const half = binary.length / 2; + for (let i = 0, j = binary.length - 1; i <= half; i++, j--) { + bytes[i] = binary.charCodeAt(i); + bytes[j] = binary.charCodeAt(j); + } + return bytes; +}; diff --git a/packages/jwt/src/utils/utf8/index.ts b/packages/jwt/src/utils/utf8/index.ts new file mode 100644 index 0000000..09bb615 --- /dev/null +++ b/packages/jwt/src/utils/utf8/index.ts @@ -0,0 +1,7 @@ +/** + * @module + * Functions for encoding/decoding UTF8. + */ + +export const utf8Encoder: TextEncoder = new TextEncoder(); +export const utf8Decoder: TextDecoder = new TextDecoder(); diff --git a/packages/jwt/src/utils/utf8/utf8.test.ts b/packages/jwt/src/utils/utf8/utf8.test.ts new file mode 100644 index 0000000..71180f9 --- /dev/null +++ b/packages/jwt/src/utils/utf8/utf8.test.ts @@ -0,0 +1,27 @@ +import { utf8Decoder, utf8Encoder } from './index'; + +describe('UTF8 Encoder/Decoder', () => { + test('utf8Encoder should encode a string to a Uint8Array', () => { + const input = 'Hello, World!'; + const encoded = utf8Encoder.encode(input); + const expected = new Uint8Array([72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33]); + + expect(encoded).toEqual(expected); + }); + + test('utf8Decoder should decode a Uint8Array to a string', () => { + const input = new Uint8Array([72, 101, 108, 108, 111, 44, 32, 87, 111, 114, 108, 100, 33]); + const decoded = utf8Decoder.decode(input); + const expected = 'Hello, World!'; + + expect(decoded).toBe(expected); + }); + + test('utf8Encoder should encode and utf8Decoder should decode correctly for non-ASCII characters', () => { + const input = 'こんにちは世界'; + const encoded = utf8Encoder.encode(input); + const decoded = utf8Decoder.decode(encoded); + + expect(decoded).toBe(input); + }); +}); diff --git a/packages/jwt/tsconfig.json b/packages/jwt/tsconfig.json new file mode 100644 index 0000000..b4767e5 --- /dev/null +++ b/packages/jwt/tsconfig.json @@ -0,0 +1,13 @@ +{ + "compilerOptions": { + "target": "es2022", + "module": "ESNext", + "outDir": "./dist", + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "skipLibCheck": true, + "moduleResolution": "node", + "types": ["jest"] + } +}