From fd7a5bcd3d838ae77b487e192a7f16f209234d55 Mon Sep 17 00:00:00 2001 From: Alessandro Falezza Date: Mon, 22 Dec 2025 14:51:34 +0100 Subject: [PATCH 1/6] first naif implementation --- README.md | 2 + index.html | 47 +- package-lock.json | 4969 +++++++++++++++++++++++---- package.json | 4 +- public/apple-touch-icon-180x180.png | Bin 0 -> 1190 bytes public/favicon.ico | Bin 0 -> 846 bytes public/favicon.png | Bin 3097 -> 0 bytes public/icon512_maskable.png | Bin 73407 -> 0 bytes public/icon512_rounded.png | Bin 60626 -> 0 bytes public/logo.svg | 58 + public/manifest.json | 21 +- public/maskable-icon-512x512.png | Bin 0 -> 5083 bytes public/pwa-192x192.png | Bin 0 -> 1952 bytes public/pwa-512x512.png | Bin 0 -> 7408 bytes public/pwa-64x64.png | Bin 0 -> 729 bytes vite.config.js | 33 +- 16 files changed, 4415 insertions(+), 719 deletions(-) create mode 100644 public/apple-touch-icon-180x180.png create mode 100644 public/favicon.ico delete mode 100644 public/favicon.png delete mode 100644 public/icon512_maskable.png delete mode 100644 public/icon512_rounded.png create mode 100644 public/logo.svg create mode 100644 public/maskable-icon-512x512.png create mode 100644 public/pwa-192x192.png create mode 100644 public/pwa-512x512.png create mode 100644 public/pwa-64x64.png diff --git a/README.md b/README.md index f5adec0d..f7664f08 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ # yTestbook + + ## What is yTestbook? It's a free web application to manage software tests. It's mainly intended for handling manual tests, but in the future it will support automatic tests as well. diff --git a/index.html b/index.html index 1f991c99..9ef07c13 100644 --- a/index.html +++ b/index.html @@ -1,29 +1,26 @@ - - - - - - - yTestbook - - - - - - - - -
+ + yTestbook + + + + + + + + + + + + - - - + + +
+ + + + + \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index b0f83095..b439f952 100644 --- a/package-lock.json +++ b/package-lock.json @@ -60,6 +60,7 @@ "@types/react-router-dom": "5.3.3", "@typescript-eslint/eslint-plugin": "8.44.1", "@typescript-eslint/parser": "8.44.1", + "@vite-pwa/assets-generator": "^1.0.2", "@vitejs/plugin-react": "5.0.3", "eslint": "9.36.0", "eslint-config-prettier": "10.1.8", @@ -77,7 +78,8 @@ "sugarss": "5.0.1", "typescript": "5.9.2", "typescript-eslint": "8.44.1", - "vite": "7.1.7" + "vite": "7.1.7", + "vite-plugin-pwa": "^1.2.0" }, "engines": { "node": "22.19.0" @@ -160,9 +162,9 @@ } }, "node_modules/@babel/compat-data": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.4.tgz", - "integrity": "sha512-YsmSKC29MJwf0gF8Rjjrg5LQCmyh+j/nD8/eP7f+BeoQTKYqs9RoWbjGOdy0+1Ekr68RJZMUOPVQaQisnIo4Rw==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", + "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", "dev": true, "license": "MIT", "engines": { @@ -211,14 +213,14 @@ } }, "node_modules/@babel/generator": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", - "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", + "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.28.3", - "@babel/types": "^7.28.2", + "@babel/parser": "^7.28.5", + "@babel/types": "^7.28.5", "@jridgewell/gen-mapping": "^0.3.12", "@jridgewell/trace-mapping": "^0.3.28", "jsesc": "^3.0.2" @@ -227,6 +229,19 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.27.3", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz", + "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.3" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-compilation-targets": { "version": "7.27.2", "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", @@ -254,6 +269,83 @@ "semver": "bin/semver.js" } }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.28.5.tgz", + "integrity": "sha512-q3WC4JfdODypvxArsJQROfupPBq9+lMwjKq7C33GhbFYJsufD0yd/ziwD+hJucLeWsnFPWZjsU2DNFqBPE7jwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-member-expression-to-functions": "^7.28.5", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/traverse": "^7.28.5", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz", + "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "regexpu-core": "^6.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.5.tgz", + "integrity": "sha512-uJnGFcPsWQK8fvjgGP5LZUZZsYGIoPeRjSF5PGwrelYgq7Q15/Ft9NGFp1zglwgIv//W0uG4BevRuSJRyylZPg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "debug": "^4.4.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.22.10" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/@babel/helper-globals": { "version": "7.28.0", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", @@ -264,6 +356,20 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz", + "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.5", + "@babel/types": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-module-imports": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", @@ -296,6 +402,19 @@ "@babel/core": "^7.0.0" } }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz", + "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-plugin-utils": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", @@ -306,6 +425,56 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz", + "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-wrap-function": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.27.1.tgz", + "integrity": "sha512-7EHz6qDZc8RYS5ElPoShMheWvEgERonFCs7IAonWLLUTXW59DP14bCZt89/GKyreYn8g3S83m21FelHKbeDCKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.27.1", + "@babel/helper-optimise-call-expression": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz", + "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.27.1", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helper-string-parser": { "version": "7.27.1", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", @@ -317,9 +486,9 @@ } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", - "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, "license": "MIT", "engines": { @@ -336,6 +505,21 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.3.tgz", + "integrity": "sha512-zdf983tNfLZFletc0RRXYrHrucBEg95NIFMkn6K9dbeMYnsgHaSBGcQqdsCSStG2PYwRre0Qc2NNSCXbG+xc6g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/traverse": "^7.28.3", + "@babel/types": "^7.28.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, "node_modules/@babel/helpers": { "version": "7.28.4", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", @@ -351,13 +535,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", - "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", + "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.28.4" + "@babel/types": "^7.28.5" }, "bin": { "parser": "bin/babel-parser.js" @@ -366,10 +550,27 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-transform-react-jsx-self": { + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz", + "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz", + "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==", "dev": true, "license": "MIT", "dependencies": { @@ -379,13 +580,13 @@ "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/plugin-transform-react-jsx-source": { + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz", + "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==", "dev": true, "license": "MIT", "dependencies": { @@ -395,880 +596,2414 @@ "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/runtime": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", - "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz", + "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==", + "dev": true, "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.27.1" + }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" } }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.3.tgz", + "integrity": "sha512-b6YTX108evsvE4YgWyQ921ZAFFQm3Bn+CA3+ZXlNVnPhx+UfsVURoPjfGAPCjBgrqo30yX/C2nZGX96DxvR9Iw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.3" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@babel/traverse": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.4.tgz", - "integrity": "sha512-YEzuboP2qvQavAcjgQNVgsvHIDv6ZpwXvcvjmyySP2DIMuByS/6ioU5G9pYrWHM6T2YDfc7xga9iNzYOs12CFQ==", + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.27.1.tgz", + "integrity": "sha512-UT/Jrhw57xg4ILHLFnzFpPDlMbcdEicaAtjPQpbj9wa8T4r5KVWCimHcL/460g8Ht0DMxDyjsLgiWSkVjnwPFg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.3", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.4", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4", - "debug": "^4.3.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/types": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", - "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.27.1.tgz", + "integrity": "sha512-oFT0FrKHgF53f4vOsZGi2Hh3I35PfSmVs4IBFLFj4dnafP+hIWDLg3VyKmUHfLoLHlyxY4C7DGtmHuJgn+IGww==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1" + "@babel/helper-plugin-utils": "^7.27.1" }, "engines": { "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@cbor-extract/cbor-extract-darwin-arm64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-arm64/-/cbor-extract-darwin-arm64-2.2.0.tgz", - "integrity": "sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } }, - "node_modules/@cbor-extract/cbor-extract-darwin-x64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-x64/-/cbor-extract-darwin-x64-2.2.0.tgz", - "integrity": "sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz", + "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@cbor-extract/cbor-extract-linux-arm": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm/-/cbor-extract-linux-arm-2.2.0.tgz", - "integrity": "sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q==", - "cpu": [ - "arm" - ], + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.28.0.tgz", + "integrity": "sha512-BEOdvX4+M765icNPZeidyADIvQ1m1gmunXufXxvRESy/jNNyfovIqUyE7MVgGBjWktCoJlzvFA1To2O4ymIO3Q==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@cbor-extract/cbor-extract-linux-arm64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm64/-/cbor-extract-linux-arm64-2.2.0.tgz", - "integrity": "sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@cbor-extract/cbor-extract-linux-x64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-x64/-/cbor-extract-linux-x64-2.2.0.tgz", - "integrity": "sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@cbor-extract/cbor-extract-win32-x64": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-win32-x64/-/cbor-extract-win32-x64-2.2.0.tgz", - "integrity": "sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1", + "@babel/traverse": "^7.28.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", - "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.27.1.tgz", + "integrity": "sha512-NREkZsZVJS4xmTr8qzE5y8AfIPqsdQfRuUiLRTEzb7Qii8iFWCyDKaUV2c0rCuh4ljDZ98ALHP/PetiBV2nddA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], + "dependencies": { + "@babel/helper-module-imports": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-remap-async-to-generator": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", - "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", - "cpu": [ - "arm" - ], + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz", + "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", - "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.5.tgz", + "integrity": "sha512-45DmULpySVvmq9Pj3X9B+62Xe+DJGov27QravQJU1LLcapR6/10i+gYVAucGGJpHBp5mYxIMK4nDAT/QDLr47g==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", - "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.27.1.tgz", + "integrity": "sha512-D0VcalChDMtuRvJIu3U/fwWjf8ZMykz5iZsg77Nuj821vCKI3zCyRLwRdWbsuJ/uRwZhZ002QtCqIkwC/ZkvbA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", - "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.3.tgz", + "integrity": "sha512-LtPXlBbRoc4Njl/oh1CeD/3jC+atytbnf/UqLoqTDcEYGUPj022+rvfkbDYieUrSj3CaV4yHDByPE+T2HwfsJg==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.28.3", + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", - "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-classes": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.4.tgz", + "integrity": "sha512-cFOlhIYPBv/iBoc+KS3M6et2XPtbT2HiCRfBXWtfpc9OAyostldxIf9YAYB6ypURBBbx+Qv6nyrLzASfJe+hBA==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.3", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-globals": "^7.28.0", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1", + "@babel/traverse": "^7.28.4" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", - "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.27.1.tgz", + "integrity": "sha512-lj9PGWvMTVksbWiDT2tW68zGS/cyo4AkZ/QTp0sQT0mjPopCmrSkzxeXkznjqBxzDI6TclZhOJbBmbBLjuOZUw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/template": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", - "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz", + "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.28.5" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", - "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", - "cpu": [ - "arm" - ], + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.27.1.tgz", + "integrity": "sha512-gEbkDVGRvjj7+T1ivxrfgygpT7GUd4vmODtYpbs0gZATdkX8/iSnOtZSxiZnsgm1YjTgjI6VKBGSJJevkrclzw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", - "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", - "cpu": [ - "arm64" - ], + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz", + "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", - "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", - "cpu": [ - "ia32" - ], + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-hkGcueTEzuhB30B3eJCbCYeCaaEQOmQR0AdvzpD4LoN0GXMWzzGSuRrxR2xTnCrvNbVwK9N6/jQ92GSLfiZWoQ==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", - "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", - "cpu": [ - "loong64" - ], + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz", + "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", - "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", - "cpu": [ - "mips64el" - ], + "node_modules/@babel/plugin-transform-explicit-resource-management": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.0.tgz", + "integrity": "sha512-K8nhUcn3f6iB+P3gwCv/no7OdzOZQcKchW6N389V6PD8NUWKZHzndOd9sPDVbMoBsbmjMqlB4L9fm+fEFNVlwQ==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", - "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", - "cpu": [ - "ppc64" - ], + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.5.tgz", + "integrity": "sha512-D4WIMaFtwa2NizOp+dnoFjRez/ClKiC2BqqImwKd1X28nqBtZEyCYJ2ozQrrzlxAFrcrjxo39S6khe9RNDlGzw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", - "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", - "cpu": [ - "riscv64" - ], + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz", + "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", - "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", - "cpu": [ - "s390x" - ], + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz", + "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", - "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", - "cpu": [ - "x64" - ], + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz", + "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==", + "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/traverse": "^7.27.1" + }, "engines": { - "node": ">=18" + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.27.1.tgz", + "integrity": "sha512-6WVLVJiTjqcQauBhn1LkICsR2H+zm62I3h9faTDKt1qP4jn2o72tSvqMwtGFKGTpojce0gJs+76eZ2uCHRZh0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz", + "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.5.tgz", + "integrity": "sha512-axUuqnUTBuXyHGcJEVVh9pORaN6wC5bYfE7FGzPiaWa3syib9m7g+/IT/4VgCOe2Upef43PHzeAvcrVek6QuuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz", + "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz", + "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.27.1.tgz", + "integrity": "sha512-OJguuwlTYlN0gBZFRPqwOGNWssZjfIUdS7HMYtN8c1KmwpwHFBwTeFZrg9XZa+DFTitWOW5iTAG7tyCUPsCCyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.28.5.tgz", + "integrity": "sha512-vn5Jma98LCOeBy/KpeQhXcV2WZgaRUtjwQmjoBuLNlOmkg0fB5pdvYVeWRYI69wWKwK2cD1QbMiUQnoujWvrew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.28.3", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz", + "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.27.1.tgz", + "integrity": "sha512-SstR5JYy8ddZvD6MhV0tM/j16Qds4mIpJTOd1Yu9J9pJjH93bxHECF7pgtc28XvkzTD6Pxcm/0Z73Hvk7kb3Ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz", + "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.27.1.tgz", + "integrity": "sha512-aGZh6xMo6q9vq1JGcw58lZ1Z0+i0xB2x0XaauNIUXd6O1xXc3RwoWEBlsTQrY4KQ9Jf0s5rgD6SiNkaUdJegTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.27.1.tgz", + "integrity": "sha512-fdPKAcujuvEChxDBJ5c+0BTaS6revLV7CJL08e4m3de8qJfNIuCc2nc7XJYOjBoTMJeqSmwXJ0ypE14RCjLwaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.4.tgz", + "integrity": "sha512-373KA2HQzKhQCYiRVIRr+3MjpCObqzDlyrM6u4I201wL8Mp2wHf7uB8GhDwis03k2ti8Zr65Zyyqs1xOxUF/Ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.0", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/traverse": "^7.28.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz", + "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-replace-supers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.27.1.tgz", + "integrity": "sha512-txEAEKzYrHEX4xSZN4kJ+OfKXFVSWKB2ZxM9dpcE3wT7smwkNmXo5ORRlVzMVdJbD+Q8ILTgSD7959uj+3Dm3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.5.tgz", + "integrity": "sha512-N6fut9IZlPnjPwgiQkXNhb+cT8wQKFlJNqcZkWlcTqkcqx6/kU4ynGmLFoa4LViBSirn05YAwk+sQBbPfxtYzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.27.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz", + "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.27.1.tgz", + "integrity": "sha512-10FVt+X55AjRAYI9BrdISN9/AQWHqldOeZDUoLyif1Kn05a56xVBXb8ZouL8pZ9jem8QpXaOt8TS7RHUIS+GPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.27.1.tgz", + "integrity": "sha512-5J+IhqTi1XPa0DXF83jYOaARrX+41gOewWbkPyjMNRDqgOCqdffGh8L3f/Ek5utaEBZExjSAzcyjmV9SSAWObQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.27.1", + "@babel/helper-create-class-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz", + "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.28.4.tgz", + "integrity": "sha512-+ZEdQlBoRg9m2NnzvEeLgtvBMO4tkFBw5SQIUgLICgTrumLoU7lr+Oghi6km2PFj+dbUt2u1oby2w3BDO9YQnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regexp-modifiers": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.27.1.tgz", + "integrity": "sha512-TtEciroaiODtXvLZv4rmfMhkCv8jx3wgKpL68PuiPh2M4fvz5jhsA7697N1gMvkvr/JTF13DrFYyEbY9U7cVPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz", + "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz", + "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.27.1.tgz", + "integrity": "sha512-kpb3HUqaILBJcRFVhFUs6Trdd4mkrzcGXss+6/mxUd273PfbWqSDHRzMT2234gIg2QYfAjvXLSquP1xECSg09Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz", + "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz", + "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz", + "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz", + "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.27.1.tgz", + "integrity": "sha512-uW20S39PnaTImxp39O5qFlHLS9LJEmANjMG7SxIhap8rCHqu0Ik+tLEPX5DKmHn6CsWQ7j3lix2tFOa5YtL12Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz", + "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.27.1.tgz", + "integrity": "sha512-EtkOujbc4cgvb0mlpQefi4NTPBzhSIevblFevACNLUspmrALgmEBdL/XfnyyITfd8fKBZrZys92zOWcik7j9Tw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.27.1", + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.28.5.tgz", + "integrity": "sha512-S36mOoi1Sb6Fz98fBfE+UZSpYw5mJm0NUHtIKrOuNcqeFauy1J6dIvXm2KRVKobOSaGq4t/hBXdN4HGU3wL9Wg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.5", + "@babel/helper-compilation-targets": "^7.27.2", + "@babel/helper-plugin-utils": "^7.27.1", + "@babel/helper-validator-option": "^7.27.1", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.3", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-import-assertions": "^7.27.1", + "@babel/plugin-syntax-import-attributes": "^7.27.1", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.27.1", + "@babel/plugin-transform-async-generator-functions": "^7.28.0", + "@babel/plugin-transform-async-to-generator": "^7.27.1", + "@babel/plugin-transform-block-scoped-functions": "^7.27.1", + "@babel/plugin-transform-block-scoping": "^7.28.5", + "@babel/plugin-transform-class-properties": "^7.27.1", + "@babel/plugin-transform-class-static-block": "^7.28.3", + "@babel/plugin-transform-classes": "^7.28.4", + "@babel/plugin-transform-computed-properties": "^7.27.1", + "@babel/plugin-transform-destructuring": "^7.28.5", + "@babel/plugin-transform-dotall-regex": "^7.27.1", + "@babel/plugin-transform-duplicate-keys": "^7.27.1", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-dynamic-import": "^7.27.1", + "@babel/plugin-transform-explicit-resource-management": "^7.28.0", + "@babel/plugin-transform-exponentiation-operator": "^7.28.5", + "@babel/plugin-transform-export-namespace-from": "^7.27.1", + "@babel/plugin-transform-for-of": "^7.27.1", + "@babel/plugin-transform-function-name": "^7.27.1", + "@babel/plugin-transform-json-strings": "^7.27.1", + "@babel/plugin-transform-literals": "^7.27.1", + "@babel/plugin-transform-logical-assignment-operators": "^7.28.5", + "@babel/plugin-transform-member-expression-literals": "^7.27.1", + "@babel/plugin-transform-modules-amd": "^7.27.1", + "@babel/plugin-transform-modules-commonjs": "^7.27.1", + "@babel/plugin-transform-modules-systemjs": "^7.28.5", + "@babel/plugin-transform-modules-umd": "^7.27.1", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.27.1", + "@babel/plugin-transform-new-target": "^7.27.1", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.27.1", + "@babel/plugin-transform-numeric-separator": "^7.27.1", + "@babel/plugin-transform-object-rest-spread": "^7.28.4", + "@babel/plugin-transform-object-super": "^7.27.1", + "@babel/plugin-transform-optional-catch-binding": "^7.27.1", + "@babel/plugin-transform-optional-chaining": "^7.28.5", + "@babel/plugin-transform-parameters": "^7.27.7", + "@babel/plugin-transform-private-methods": "^7.27.1", + "@babel/plugin-transform-private-property-in-object": "^7.27.1", + "@babel/plugin-transform-property-literals": "^7.27.1", + "@babel/plugin-transform-regenerator": "^7.28.4", + "@babel/plugin-transform-regexp-modifiers": "^7.27.1", + "@babel/plugin-transform-reserved-words": "^7.27.1", + "@babel/plugin-transform-shorthand-properties": "^7.27.1", + "@babel/plugin-transform-spread": "^7.27.1", + "@babel/plugin-transform-sticky-regex": "^7.27.1", + "@babel/plugin-transform-template-literals": "^7.27.1", + "@babel/plugin-transform-typeof-symbol": "^7.27.1", + "@babel/plugin-transform-unicode-escapes": "^7.27.1", + "@babel/plugin-transform-unicode-property-regex": "^7.27.1", + "@babel/plugin-transform-unicode-regex": "^7.27.1", + "@babel/plugin-transform-unicode-sets-regex": "^7.27.1", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.14", + "babel-plugin-polyfill-corejs3": "^0.13.0", + "babel-plugin-polyfill-regenerator": "^0.6.5", + "core-js-compat": "^3.43.0", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", + "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/generator": "^7.28.5", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.28.5", + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.5", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", + "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@canvas/image-data": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@canvas/image-data/-/image-data-1.1.0.tgz", + "integrity": "sha512-QdObRRjRbcXGmM1tmJ+MrHcaz1MftF2+W7YI+MsphnsCrmtyfS0d5qJbk0MeSbUeyM/jCb0hmnkXPsy026L7dA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@cbor-extract/cbor-extract-darwin-arm64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-arm64/-/cbor-extract-darwin-arm64-2.2.0.tgz", + "integrity": "sha512-P7swiOAdF7aSi0H+tHtHtr6zrpF3aAq/W9FXx5HektRvLTM2O89xCyXF3pk7pLc7QpaY7AoaE8UowVf9QBdh3w==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@cbor-extract/cbor-extract-darwin-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-darwin-x64/-/cbor-extract-darwin-x64-2.2.0.tgz", + "integrity": "sha512-1liF6fgowph0JxBbYnAS7ZlqNYLf000Qnj4KjqPNW4GViKrEql2MgZnAsExhY9LSy8dnvA4C0qHEBgPrll0z0w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@cbor-extract/cbor-extract-linux-arm": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm/-/cbor-extract-linux-arm-2.2.0.tgz", + "integrity": "sha512-QeBcBXk964zOytiedMPQNZr7sg0TNavZeuUCD6ON4vEOU/25+pLhNN6EDIKJ9VLTKaZ7K7EaAriyYQ1NQ05s/Q==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@cbor-extract/cbor-extract-linux-arm64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-arm64/-/cbor-extract-linux-arm64-2.2.0.tgz", + "integrity": "sha512-rQvhNmDuhjTVXSPFLolmQ47/ydGOFXtbR7+wgkSY0bdOxCFept1hvg59uiLPT2fVDuJFuEy16EImo5tE2x3RsQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@cbor-extract/cbor-extract-linux-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-linux-x64/-/cbor-extract-linux-x64-2.2.0.tgz", + "integrity": "sha512-cWLAWtT3kNLHSvP4RKDzSTX9o0wvQEEAj4SKvhWuOVZxiDAeQazr9A+PSiRILK1VYMLeDml89ohxCnUNQNQNCw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@cbor-extract/cbor-extract-win32-x64": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/@cbor-extract/cbor-extract-win32-x64/-/cbor-extract-win32-x64-2.2.0.tgz", + "integrity": "sha512-l2M+Z8DO2vbvADOBNLbbh9y5ST1RY5sqkWOg/58GkUPBYou/cuNZ68SGQ644f1CvZ8kcOxyZtw06+dxWHIoN/w==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@emnapi/runtime": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", + "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "tslib": "^2.4.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.10.tgz", + "integrity": "sha512-0NFWnA+7l41irNuaSVlLfgNT12caWJVLzp5eAVhZ0z1qpxbockccEt3s+149rE64VUI3Ml2zt8Nv5JVc4QXTsw==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.10.tgz", + "integrity": "sha512-dQAxF1dW1C3zpeCDc5KqIYuZ1tgAdRXNoZP7vkBIRtKZPYe2xVr/d3SkirklCHudW1B45tGiUlz2pUWDfbDD4w==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.10.tgz", + "integrity": "sha512-LSQa7eDahypv/VO6WKohZGPSJDq5OVOo3UoFR1E4t4Gj1W7zEQMUhI+lo81H+DtB+kP+tDgBp+M4oNCwp6kffg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.10.tgz", + "integrity": "sha512-MiC9CWdPrfhibcXwr39p9ha1x0lZJ9KaVfvzA0Wxwz9ETX4v5CHfF09bx935nHlhi+MxhA63dKRRQLiVgSUtEg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.10.tgz", + "integrity": "sha512-JC74bdXcQEpW9KkV326WpZZjLguSZ3DfS8wrrvPMHgQOIEIG/sPXEN/V8IssoJhbefLRcRqw6RQH2NnpdprtMA==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.10.tgz", + "integrity": "sha512-tguWg1olF6DGqzws97pKZ8G2L7Ig1vjDmGTwcTuYHbuU6TTjJe5FXbgs5C1BBzHbJ2bo1m3WkQDbWO2PvamRcg==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.10.tgz", + "integrity": "sha512-3ZioSQSg1HT2N05YxeJWYR+Libe3bREVSdWhEEgExWaDtyFbbXWb49QgPvFH8u03vUPX10JhJPcz7s9t9+boWg==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.10.tgz", + "integrity": "sha512-LLgJfHJk014Aa4anGDbh8bmI5Lk+QidDmGzuC2D+vP7mv/GeSN+H39zOf7pN5N8p059FcOfs2bVlrRr4SK9WxA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.10.tgz", + "integrity": "sha512-oR31GtBTFYCqEBALI9r6WxoU/ZofZl962pouZRTEYECvNF/dtXKku8YXcJkhgK/beU+zedXfIzHijSRapJY3vg==", + "cpu": [ + "arm" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.10.tgz", + "integrity": "sha512-5luJWN6YKBsawd5f9i4+c+geYiVEw20FVW5x0v1kEMWNq8UctFjDiMATBxLvmmHA4bf7F6hTRaJgtghFr9iziQ==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.10.tgz", + "integrity": "sha512-NrSCx2Kim3EnnWgS4Txn0QGt0Xipoumb6z6sUtl5bOEZIVKhzfyp/Lyw4C1DIYvzeW/5mWYPBFJU3a/8Yr75DQ==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.10.tgz", + "integrity": "sha512-xoSphrd4AZda8+rUDDfD9J6FUMjrkTz8itpTITM4/xgerAZZcFW7Dv+sun7333IfKxGG8gAq+3NbfEMJfiY+Eg==", + "cpu": [ + "loong64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.10.tgz", + "integrity": "sha512-ab6eiuCwoMmYDyTnyptoKkVS3k8fy/1Uvq7Dj5czXI6DF2GqD2ToInBI0SHOp5/X1BdZ26RKc5+qjQNGRBelRA==", + "cpu": [ + "mips64el" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.10.tgz", + "integrity": "sha512-NLinzzOgZQsGpsTkEbdJTCanwA5/wozN9dSgEl12haXJBzMTpssebuXR42bthOF3z7zXFWH1AmvWunUCkBE4EA==", + "cpu": [ + "ppc64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.10.tgz", + "integrity": "sha512-FE557XdZDrtX8NMIeA8LBJX3dC2M8VGXwfrQWU7LB5SLOajfJIxmSdyL/gU1m64Zs9CBKvm4UAuBp5aJ8OgnrA==", + "cpu": [ + "riscv64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.10.tgz", + "integrity": "sha512-3BBSbgzuB9ajLoVZk0mGu+EHlBwkusRmeNYdqmznmMc9zGASFjSsxgkNsqmXugpPk00gJ0JNKh/97nxmjctdew==", + "cpu": [ + "s390x" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.10.tgz", + "integrity": "sha512-QSX81KhFoZGwenVyPoberggdW1nrQZSvfVDAIUXr3WqLRZGZqWk/P4T8p2SP+de2Sr5HPcvjhcJzEiulKgnxtA==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", + "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", + "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", + "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", + "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", + "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", + "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", + "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", + "cpu": [ + "arm64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", + "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", + "cpu": [ + "ia32" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.25.10", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", + "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", + "cpu": [ + "x64" + ], + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/compat": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.4.0.tgz", + "integrity": "sha512-DEzm5dKeDBPm3r08Ixli/0cmxr8LkRdwxMRUIJBlSCpAwSrvFEJpVBzV+66JhDxiaqKxnRzCXhtiMiczF7Hglg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.16.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": "^8.40 || 9" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.0", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", + "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.6", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", + "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz", + "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.36.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz", + "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", + "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", + "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.15.2", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", + "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@floating-ui/core": { + "version": "1.7.3", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", + "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", + "license": "MIT", + "dependencies": { + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/dom": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", + "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", + "license": "MIT", + "dependencies": { + "@floating-ui/core": "^1.7.3", + "@floating-ui/utils": "^0.2.10" + } + }, + "node_modules/@floating-ui/react": { + "version": "0.27.16", + "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.16.tgz", + "integrity": "sha512-9O8N4SeG2z++TSM8QA/KTeKFBVCNEz/AGS7gWPJf6KFRzmRWixFRnCnkPHRDwSVZW6QPDO6uT0P2SpWNKCc9/g==", + "license": "MIT", + "dependencies": { + "@floating-ui/react-dom": "^2.1.6", + "@floating-ui/utils": "^0.2.10", + "tabbable": "^6.0.0" + }, + "peerDependencies": { + "react": ">=17.0.0", + "react-dom": ">=17.0.0" + } + }, + "node_modules/@floating-ui/react-dom": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz", + "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==", + "license": "MIT", + "dependencies": { + "@floating-ui/dom": "^1.7.4" + }, + "peerDependencies": { + "react": ">=16.8.0", + "react-dom": ">=16.8.0" + } + }, + "node_modules/@floating-ui/utils": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", + "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", + "license": "MIT" + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@ianvs/prettier-plugin-sort-imports": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@ianvs/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.7.0.tgz", + "integrity": "sha512-soa2bPUJAFruLL4z/CnMfSEKGznm5ebz29fIa9PxYtu8HHyLKNE1NXAs6dylfw1jn/ilEIfO2oLLN6uAafb7DA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@babel/generator": "^7.26.2", + "@babel/parser": "^7.26.2", + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.26.0", + "semver": "^7.5.2" + }, + "peerDependencies": { + "@prettier/plugin-oxc": "^0.0.4", + "@vue/compiler-sfc": "2.7.x || 3.x", + "content-tag": "^4.0.0", + "prettier": "2 || 3 || ^4.0.0-0", + "prettier-plugin-ember-template-tag": "^2.1.0" + }, + "peerDependenciesMeta": { + "@prettier/plugin-oxc": { + "optional": true + }, + "@vue/compiler-sfc": { + "optional": true + }, + "content-tag": { + "optional": true + }, + "prettier-plugin-ember-template-tag": { + "optional": true + } } }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.10.tgz", - "integrity": "sha512-AKQM3gfYfSW8XRk8DdMCzaLUFB15dTrZfnX8WXQoOUpUBQ+NaAFCP1kPS/ykbbGYz7rxn0WS48/81l9hFl3u4A==", + "node_modules/@img/sharp-darwin-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", + "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", "cpu": [ "arm64" ], - "license": "MIT", + "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ - "netbsd" + "darwin" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-arm64": "1.0.4" } }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.10.tgz", - "integrity": "sha512-7RTytDPGU6fek/hWuN9qQpeGPBZFfB4zZgcz2VK2Z5VpdUxEI8JKYsg3JfO0n/Z1E/6l05n0unDCNc4HnhQGig==", + "node_modules/@img/sharp-darwin-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", + "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", "cpu": [ "x64" ], - "license": "MIT", + "dev": true, + "license": "Apache-2.0", "optional": true, "os": [ - "netbsd" + "darwin" ], "engines": { - "node": ">=18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-darwin-x64": "1.0.4" } }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.10.tgz", - "integrity": "sha512-5Se0VM9Wtq797YFn+dLimf2Zx6McttsH2olUBsDml+lm0GOCRVebRWUvDtkY4BWYv/3NgzS8b/UM3jQNh5hYyw==", + "node_modules/@img/sharp-libvips-darwin-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", + "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", "cpu": [ "arm64" ], - "license": "MIT", + "dev": true, + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "openbsd" + "darwin" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.10.tgz", - "integrity": "sha512-XkA4frq1TLj4bEMB+2HnI0+4RnjbuGZfet2gs/LNs5Hc7D89ZQBHQ0gL2ND6Lzu1+QVkjp3x1gIcPKzRNP8bXw==", + "node_modules/@img/sharp-libvips-darwin-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", + "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", "cpu": [ "x64" ], - "license": "MIT", + "dev": true, + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "openbsd" + "darwin" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.10.tgz", - "integrity": "sha512-AVTSBhTX8Y/Fz6OmIVBip9tJzZEUcY8WLh7I59+upa5/GPhh2/aM6bvOMQySspnCCHvFi79kMtdJS1w0DXAeag==", + "node_modules/@img/sharp-libvips-linux-arm": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", + "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", "cpu": [ - "arm64" + "arm" ], - "license": "MIT", + "dev": true, + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "openharmony" + "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.10.tgz", - "integrity": "sha512-fswk3XT0Uf2pGJmOpDB7yknqhVkJQkAQOcW/ccVOtfx05LkbWOaRAtn5SaqXypeKQra1QaEa841PgrSL9ubSPQ==", + "node_modules/@img/sharp-libvips-linux-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", + "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", "cpu": [ - "x64" + "arm64" ], - "license": "MIT", + "dev": true, + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "sunos" + "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.10.tgz", - "integrity": "sha512-ah+9b59KDTSfpaCg6VdJoOQvKjI33nTaQr4UluQwW7aEwZQsbMCfTmfEO4VyewOxx4RaDT/xCy9ra2GPWmO7Kw==", + "node_modules/@img/sharp-libvips-linux-s390x": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", + "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", "cpu": [ - "arm64" + "s390x" ], - "license": "MIT", + "dev": true, + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "win32" + "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.10.tgz", - "integrity": "sha512-QHPDbKkrGO8/cz9LKVnJU22HOi4pxZnZhhA2HYHez5Pz4JeffhDjf85E57Oyco163GnzNCVkZK0b/n4Y0UHcSw==", + "node_modules/@img/sharp-libvips-linux-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", + "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", "cpu": [ - "ia32" + "x64" ], - "license": "MIT", + "dev": true, + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "win32" + "linux" ], - "engines": { - "node": ">=18" + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.10", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.10.tgz", - "integrity": "sha512-9KpxSVFCu0iK1owoez6aC/s/EdUQLDN3adTxGCqxMVhrPDj6bt5dbrHDXUuq+Bs2vATFBBrQS5vdQ/Ed2P+nbw==", + "node_modules/@img/sharp-libvips-linuxmusl-arm64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", + "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", "cpu": [ - "x64" + "arm64" ], - "license": "MIT", + "dev": true, + "license": "LGPL-3.0-or-later", "optional": true, "os": [ - "win32" + "linux" ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@eslint-community/eslint-utils": { - "version": "4.9.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", - "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, "funding": { - "url": "https://opencollective.com/eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" - } - }, - "node_modules/@eslint-community/regexpp": { - "version": "4.12.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", - "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^12.0.0 || ^14.0.0 || >=16.0.0" - } - }, - "node_modules/@eslint/compat": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.4.0.tgz", - "integrity": "sha512-DEzm5dKeDBPm3r08Ixli/0cmxr8LkRdwxMRUIJBlSCpAwSrvFEJpVBzV+66JhDxiaqKxnRzCXhtiMiczF7Hglg==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.16.0" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - }, - "peerDependencies": { - "eslint": "^8.40 || 9" - }, - "peerDependenciesMeta": { - "eslint": { - "optional": true - } - } - }, - "node_modules/@eslint/config-array": { - "version": "0.21.0", - "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz", - "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@eslint/object-schema": "^2.1.6", - "debug": "^4.3.1", - "minimatch": "^3.1.2" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "url": "https://opencollective.com/libvips" } }, - "node_modules/@eslint/config-helpers": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz", - "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==", + "node_modules/@img/sharp-libvips-linuxmusl-x64": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", + "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "license": "LGPL-3.0-or-later", + "optional": true, + "os": [ + "linux" + ], + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@eslint/core": { - "version": "0.16.0", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz", - "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==", + "node_modules/@img/sharp-linux-arm": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", + "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", + "cpu": [ + "arm" + ], "dev": true, "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", - "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^10.0.1", - "globals": "^14.0.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", - "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" + "url": "https://opencollective.com/libvips" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "@img/sharp-libvips-linux-arm": "1.0.5" } }, - "node_modules/@eslint/js": { - "version": "9.36.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz", - "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==", + "node_modules/@img/sharp-linux-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", + "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "url": "https://eslint.org/donate" + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-arm64": "1.0.4" } }, - "node_modules/@eslint/object-schema": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz", - "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==", + "node_modules/@img/sharp-linux-s390x": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", + "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", + "cpu": [ + "s390x" + ], "dev": true, "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-s390x": "1.0.4" } }, - "node_modules/@eslint/plugin-kit": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz", - "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==", + "node_modules/@img/sharp-linux-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", + "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", + "cpu": [ + "x64" + ], "dev": true, "license": "Apache-2.0", - "dependencies": { - "@eslint/core": "^0.15.2", - "levn": "^0.4.1" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linux-x64": "1.0.4" } }, - "node_modules/@eslint/plugin-kit/node_modules/@eslint/core": { - "version": "0.15.2", - "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz", - "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==", + "node_modules/@img/sharp-linuxmusl-arm64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", + "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", + "cpu": [ + "arm64" + ], "dev": true, "license": "Apache-2.0", - "dependencies": { - "@types/json-schema": "^7.0.15" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/@floating-ui/core": { - "version": "1.7.3", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.3.tgz", - "integrity": "sha512-sGnvb5dmrJaKEZ+LDIpguvdX3bDlEllmv4/ClQ9awcmCZrlx5jQyyMWFM5kBI+EyNOCDDiKk8il0zeuX3Zlg/w==", - "license": "MIT", - "dependencies": { - "@floating-ui/utils": "^0.2.10" - } - }, - "node_modules/@floating-ui/dom": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.4.tgz", - "integrity": "sha512-OOchDgh4F2CchOX94cRVqhvy7b3AFb+/rQXyswmzmGakRfkMgoWVjfnLWkRirfLEfuD4ysVW16eXzwt3jHIzKA==", - "license": "MIT", - "dependencies": { - "@floating-ui/core": "^1.7.3", - "@floating-ui/utils": "^0.2.10" - } - }, - "node_modules/@floating-ui/react": { - "version": "0.27.16", - "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.27.16.tgz", - "integrity": "sha512-9O8N4SeG2z++TSM8QA/KTeKFBVCNEz/AGS7gWPJf6KFRzmRWixFRnCnkPHRDwSVZW6QPDO6uT0P2SpWNKCc9/g==", - "license": "MIT", - "dependencies": { - "@floating-ui/react-dom": "^2.1.6", - "@floating-ui/utils": "^0.2.10", - "tabbable": "^6.0.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, - "peerDependencies": { - "react": ">=17.0.0", - "react-dom": ">=17.0.0" - } - }, - "node_modules/@floating-ui/react-dom": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.6.tgz", - "integrity": "sha512-4JX6rEatQEvlmgU80wZyq9RT96HZJa88q8hp0pBd+LrczeDI4o6uA2M+uvxngVHo4Ihr8uibXxH6+70zhAFrVw==", - "license": "MIT", - "dependencies": { - "@floating-ui/dom": "^1.7.4" + "funding": { + "url": "https://opencollective.com/libvips" }, - "peerDependencies": { - "react": ">=16.8.0", - "react-dom": ">=16.8.0" + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" } }, - "node_modules/@floating-ui/utils": { - "version": "0.2.10", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.10.tgz", - "integrity": "sha512-aGTxbpbg8/b5JfU1HXSrbH3wXZuLPJcNEcZQFMxLs3oSzgtVu6nFPkbbGGUvBcUjKV2YyB9Wxxabo+HEH9tcRQ==", - "license": "MIT" - }, - "node_modules/@humanfs/core": { - "version": "0.19.1", - "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", - "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "node_modules/@img/sharp-linuxmusl-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", + "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", + "cpu": [ + "x64" + ], "dev": true, "license": "Apache-2.0", + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=18.18.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-libvips-linuxmusl-x64": "1.0.4" } }, - "node_modules/@humanfs/node": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", - "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "node_modules/@img/sharp-wasm32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", + "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", + "cpu": [ + "wasm32" + ], "dev": true, - "license": "Apache-2.0", + "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", + "optional": true, "dependencies": { - "@humanfs/core": "^0.19.1", - "@humanwhocodes/retry": "^0.4.0" + "@emnapi/runtime": "^1.2.0" }, "engines": { - "node": ">=18.18.0" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" } }, - "node_modules/@humanwhocodes/module-importer": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", - "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "node_modules/@img/sharp-win32-ia32": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", + "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", + "cpu": [ + "ia32" + ], "dev": true, - "license": "Apache-2.0", + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=12.22" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "url": "https://opencollective.com/libvips" } }, - "node_modules/@humanwhocodes/retry": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", - "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "node_modules/@img/sharp-win32-x64": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", + "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", + "cpu": [ + "x64" + ], "dev": true, - "license": "Apache-2.0", + "license": "Apache-2.0 AND LGPL-3.0-or-later", + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=18.18" + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" }, "funding": { - "type": "github", - "url": "https://github.com/sponsors/nzakas" + "url": "https://opencollective.com/libvips" } }, - "node_modules/@ianvs/prettier-plugin-sort-imports": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@ianvs/prettier-plugin-sort-imports/-/prettier-plugin-sort-imports-4.7.0.tgz", - "integrity": "sha512-soa2bPUJAFruLL4z/CnMfSEKGznm5ebz29fIa9PxYtu8HHyLKNE1NXAs6dylfw1jn/ilEIfO2oLLN6uAafb7DA==", + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "dev": true, + "license": "MIT", "dependencies": { - "@babel/generator": "^7.26.2", - "@babel/parser": "^7.26.2", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.26.0", - "semver": "^7.5.2" + "@isaacs/balanced-match": "^4.0.1" }, - "peerDependencies": { - "@prettier/plugin-oxc": "^0.0.4", - "@vue/compiler-sfc": "2.7.x || 3.x", - "content-tag": "^4.0.0", - "prettier": "2 || 3 || ^4.0.0-0", - "prettier-plugin-ember-template-tag": "^2.1.0" + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, - "peerDependenciesMeta": { - "@prettier/plugin-oxc": { - "optional": true - }, - "@vue/compiler-sfc": { - "optional": true - }, - "content-tag": { - "optional": true - }, - "prettier-plugin-ember-template-tag": { - "optional": true - } + "engines": { + "node": ">=12" } }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.13", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@jridgewell/sourcemap-codec": "^1.5.0", @@ -1290,12 +3025,23 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, + "devOptional": true, "license": "MIT", "engines": { "node": ">=6.0.0" } }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.11", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz", + "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", @@ -1306,7 +3052,7 @@ "version": "0.3.31", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", @@ -1808,6 +3554,19 @@ "url": "https://opencollective.com/pkgr" } }, + "node_modules/@quansync/fs": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@quansync/fs/-/fs-1.0.0.tgz", + "integrity": "sha512-4TJ3DFtlf1L5LDMaM6CanJ/0lckGNtJcMjQ1NAV6zDmA0tEHKZtxNKin8EgPaVX1YzljbxckyT2tJrpQKAtngQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "quansync": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sxzz" + } + }, "node_modules/@remirror/core-constants": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/@remirror/core-constants/-/core-constants-3.0.0.tgz", @@ -1819,7 +3578,55 @@ "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.35.tgz", "integrity": "sha512-slYrCpoxJUqzFDDNlvrOYRazQUNRvWPjXA17dAOISY3rDMxX6k8K4cj2H+hEYMHF81HO3uNd5rHVigAWRM5dSg==", "dev": true, - "license": "MIT" + "license": "MIT" + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz", + "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-terser": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", + "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } }, "node_modules/@rollup/plugin-virtual": { "version": "3.0.2", @@ -1838,6 +3645,49 @@ } } }, + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils/node_modules/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/@rollup/rollup-android-arm-eabi": { "version": "4.52.2", "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.52.2.tgz", @@ -2131,6 +3981,29 @@ "dev": true, "license": "MIT" }, + "node_modules/@surma/rollup-plugin-off-main-thread": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/@surma/rollup-plugin-off-main-thread/-/rollup-plugin-off-main-thread-2.2.3.tgz", + "integrity": "sha512-lR8q/9W7hZpMWweNiAKU7NQerBnzQQLvi8qnTDU/fxItPhtZVMbPV3lbCwjhIlNBe9Bbr5V+KHshvWmVSG9cxQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "ejs": "^3.1.6", + "json5": "^2.2.0", + "magic-string": "^0.25.0", + "string.prototype.matchall": "^4.0.6" + } + }, + "node_modules/@surma/rollup-plugin-off-main-thread/node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, "node_modules/@swc/core": { "version": "1.13.5", "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.13.5.tgz", @@ -3037,6 +4910,20 @@ "@types/react-router": "*" } }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/use-sync-external-store": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", @@ -3314,6 +5201,30 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/@vite-pwa/assets-generator": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@vite-pwa/assets-generator/-/assets-generator-1.0.2.tgz", + "integrity": "sha512-MCbrb508JZHqe7bUibmZj/lyojdhLRnfkmyXnkrCM2zVrjTgL89U8UEfInpKTvPeTnxsw2hmyZxnhsdNR6yhwg==", + "dev": true, + "license": "MIT", + "dependencies": { + "cac": "^6.7.14", + "colorette": "^2.0.20", + "consola": "^3.4.2", + "sharp": "^0.33.5", + "sharp-ico": "^0.1.5", + "unconfig": "^7.3.1" + }, + "bin": { + "pwa-assets-generator": "bin/pwa-assets-generator.mjs" + }, + "engines": { + "node": ">=16.14.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@vitejs/plugin-react": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.0.3.tgz", @@ -3447,7 +5358,7 @@ "version": "8.15.0", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "dev": true, + "devOptional": true, "license": "MIT", "bin": { "acorn": "bin/acorn" @@ -3483,6 +5394,19 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/ansi-regex": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", + "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -3674,6 +5598,13 @@ "node": ">=12" } }, + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, "node_modules/async-function": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", @@ -3684,6 +5615,16 @@ "node": ">= 0.4" } }, + "node_modules/at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/attr-accept": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/attr-accept/-/attr-accept-2.2.5.tgz", @@ -3709,6 +5650,58 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.14.tgz", + "integrity": "sha512-Co2Y9wX854ts6U8gAAPXfn0GmAyctHuK8n0Yhfjd6t30g7yvKjspvvOo9yG+z52PZRgFErt7Ka2pYnXCjLKEpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.27.7", + "@babel/helper-define-polyfill-provider": "^0.6.5", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2/node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz", + "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5", + "core-js-compat": "^3.43.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.5.tgz", + "integrity": "sha512-ISqQ2frbiNU9vIJkzg7dlPpznPZ4jOiUQ1uSmB0fEHeowtN3COYRsXr/xexn64NpU13P06jc/L5TgiJXOgrbEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.5" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -3723,9 +5716,9 @@ "license": "MIT" }, "node_modules/baseline-browser-mapping": { - "version": "2.8.6", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.6.tgz", - "integrity": "sha512-wrH5NNqren/QMtKUEEJf7z86YjfqW/2uw3IL3/xpqZUC95SSVIFXYQeeGjL6FT/X68IROu6RMehZQS5foy2BXw==", + "version": "2.9.11", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.11.tgz", + "integrity": "sha512-Sg0xJUNDU1sJNGdfGWhVHX0kkZ+HWcvmVymJbj6NSgZZmW/8S9Y2HQ5euytnIgakgxN6papOAWiwDo1ctFDcoQ==", "dev": true, "license": "Apache-2.0", "bin": { @@ -3763,9 +5756,9 @@ } }, "node_modules/browserslist": { - "version": "4.26.2", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.26.2.tgz", - "integrity": "sha512-ECFzp6uFOSB+dcZ5BK/IBaGWssbSYBHvuMeMt3MMFyhI0Z8SqGgEkBLARgpRH3hutIgPVsALcMwbDrJqPxQ65A==", + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", "dev": true, "funding": [ { @@ -3783,11 +5776,11 @@ ], "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.8.3", - "caniuse-lite": "^1.0.30001741", - "electron-to-chromium": "^1.5.218", - "node-releases": "^2.0.21", - "update-browserslist-db": "^1.1.3" + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" }, "bin": { "browserslist": "cli.js" @@ -3815,6 +5808,13 @@ "bs58": "^5.0.0" } }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "devOptional": true, + "license": "MIT" + }, "node_modules/cac": { "version": "6.7.14", "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", @@ -3895,9 +5895,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001743", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001743.tgz", - "integrity": "sha512-e6Ojr7RV14Un7dz6ASD0aZDmQPT/A+eZU+nuTNfjqmRrmkmQlnTNWH0SKmqagx9PeW87UVqapSurtAXifmtdmw==", + "version": "1.0.30001761", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001761.tgz", + "integrity": "sha512-JF9ptu1vP2coz98+5051jZ4PwQgd2ni8A+gYSN7EA7dPKIMf0pDlSUxhdmVOaV3/fYK5uWBkgSXJaRLr4+3A6g==", "dev": true, "funding": [ { @@ -4013,6 +6013,20 @@ "node": ">=6" } }, + "node_modules/color": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", + "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1", + "color-string": "^1.9.0" + }, + "engines": { + "node": ">=12.5.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", @@ -4033,6 +6047,41 @@ "dev": true, "license": "MIT" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "node_modules/colorette": { + "version": "2.0.20", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "devOptional": true, + "license": "MIT" + }, + "node_modules/common-tags": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", + "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4.0.0" + } + }, "node_modules/compressorjs": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/compressorjs/-/compressorjs-1.2.1.tgz", @@ -4050,6 +6099,16 @@ "dev": true, "license": "MIT" }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", @@ -4066,6 +6125,20 @@ "node": ">=18" } }, + "node_modules/core-js-compat": { + "version": "3.47.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.47.0.tgz", + "integrity": "sha512-IGfuznZ/n7Kp9+nypamBhvwdwLsW6KC8IOaURw2doAK5e98AG3acVLdh0woOnEqCfUtS+Vu882JE4k/DAm3ItQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.28.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/crelt": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", @@ -4087,6 +6160,16 @@ "node": ">= 8" } }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", @@ -4183,6 +6266,35 @@ } } }, + "node_modules/decode-bmp": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/decode-bmp/-/decode-bmp-0.2.1.tgz", + "integrity": "sha512-NiOaGe+GN0KJqi2STf24hfMkFitDUaIoUU3eKvP/wAbLe8o6FuW5n/x7MHPR0HKvBokp6MQY/j7w8lewEeVCIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@canvas/image-data": "^1.0.0", + "to-data-view": "^1.1.0" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/decode-ico": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/decode-ico/-/decode-ico-0.4.1.tgz", + "integrity": "sha512-69NZfbKIzux1vBOd31al3XnMnH+2mqDhEgLdpygErm4d60N+UwA5Sq5WFjmEDQzumgB9fElojGwWG0vybVfFmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@canvas/image-data": "^1.0.0", + "decode-bmp": "^0.2.0", + "to-data-view": "^1.1.0" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/deep-eql": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", @@ -4199,6 +6311,16 @@ "dev": true, "license": "MIT" }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/define-data-property": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", @@ -4235,12 +6357,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true, + "license": "MIT" + }, "node_modules/detect-libc": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.0.tgz", "integrity": "sha512-vEtk+OcP7VBRtQZ1EJ3bdgzSfBjgnEalLTp5zjJrS+2Z1w2KZly4SBdac/WDU3hhsNAZ9E8SC96ME4Ey8MZ7cg==", + "devOptional": true, "license": "Apache-2.0", - "optional": true, "engines": { "node": ">=8" } @@ -4289,13 +6418,43 @@ "node": ">= 0.4" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "Apache-2.0", + "dependencies": { + "jake": "^10.8.5" + }, + "bin": { + "ejs": "bin/cli.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/electron-to-chromium": { - "version": "1.5.222", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.222.tgz", - "integrity": "sha512-gA7psSwSwQRE60CEoLz6JBCQPIxNeuzB2nL8vE03GK/OHxlvykbLyeiumQy1iH5C2f3YbRAZpGCMT12a/9ih9w==", + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==", "dev": true, "license": "ISC" }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -5099,6 +7258,23 @@ "integrity": "sha512-n11RGP/lrWEFI/bWdygLxhI+pVeo1ZYIVwvvPkW7azl/rOy+F3HYRZ2K5zeE9mmkhQppyv9sQFx0JM9UabnpPQ==", "license": "Unlicense" }, + "node_modules/fast-uri": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", + "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fastify" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fastify" + } + ], + "license": "BSD-3-Clause" + }, "node_modules/fastq": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", @@ -5128,10 +7304,43 @@ "integrity": "sha512-QgXo+mXTe8ljeqUFaX3QVHc5osSItJ/Km+xpocx0aSqWGMSCf6qYs/VnzZgS864Pjn5iceMRFigeAV7AfTlaig==", "license": "MIT", "dependencies": { - "tslib": "^2.7.0" + "tslib": "^2.7.0" + }, + "engines": { + "node": ">= 12" + } + }, + "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, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.0.1" + } + }, + "node_modules/filelist/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "license": "MIT", + "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, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" }, "engines": { - "node": ">= 12" + "node": ">=10" } }, "node_modules/fill-range": { @@ -5201,6 +7410,39 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/foreground-child": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", + "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.6", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fs-extra": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", + "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/fsevents": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", @@ -5300,6 +7542,13 @@ "node": ">=6" } }, + "node_modules/get-own-enumerable-property-symbols": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", + "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", + "dev": true, + "license": "ISC" + }, "node_modules/get-proto": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", @@ -5332,6 +7581,30 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/glob": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-11.1.0.tgz", + "integrity": "sha512-vuNwKSaKiqm7g0THUBu2x7ckSs3XJLXE+2ssL7/MfTGPLLcrJQ/4Uq1CjPTtO5cCIiRxqvN6Twy1qOwhL0Xjcw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "foreground-child": "^3.3.1", + "jackspeak": "^4.1.1", + "minimatch": "^10.1.1", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^2.0.0" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/glob-parent": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", @@ -5345,6 +7618,22 @@ "node": ">=10.13.0" } }, + "node_modules/glob/node_modules/minimatch": { + "version": "10.1.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.1.1.tgz", + "integrity": "sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/globals": { "version": "16.4.0", "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", @@ -5388,6 +7677,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true, + "license": "ISC" + }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", @@ -5489,6 +7785,20 @@ "node": ">= 0.4" } }, + "node_modules/ico-endec": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/ico-endec/-/ico-endec-0.1.6.tgz", + "integrity": "sha512-ZdLU38ZoED3g1j3iEyzcQj+wAkY2xfWNkymszfJPoxucIUhK7NayQ+/C4Kv0nDFMIsbtbEHldv3V8PU494/ueQ==", + "dev": true, + "license": "MPL-2.0" + }, + "node_modules/idb": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/idb/-/idb-7.1.1.tgz", + "integrity": "sha512-gchesWBzyvGHRO9W8tzUWFDycow5gwjvFKfyV9FF32Y7F50yZMp7mP+T2mJIWFx49zicqyC4uefHM17o6xKIVQ==", + "dev": true, + "license": "ISC" + }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", @@ -5566,6 +7876,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-arrayish": { + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", + "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", + "dev": true, + "license": "MIT" + }, "node_modules/is-async-function": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", @@ -5721,6 +8038,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-generator-function": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", @@ -5766,6 +8093,13 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==", + "dev": true, + "license": "MIT" + }, "node_modules/is-negative-zero": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", @@ -5806,6 +8140,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-regex": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", @@ -5825,6 +8169,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-regexp": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", + "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-set": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", @@ -5854,6 +8208,19 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/is-string": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", @@ -5992,6 +8359,50 @@ "node": ">= 0.4" } }, + "node_modules/jackspeak": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.1.1.tgz", + "integrity": "sha512-zptv57P3GpL+O0I7VdMJNBZCu+BPHVQUk55Ft8/QCJjTVxrnJHuVuX/0Bl2A6/+2oyR/ZMEuFKwmzqqZ/U5nPQ==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/jake": { + "version": "10.9.4", + "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.4.tgz", + "integrity": "sha512-wpHYzhxiVQL+IV05BLE2Xn34zW1S223hvjtqk0+gsPrwd/8JNLXJgZZM/iPFsYc1xyphF+6M6EvdE5E9MBGkDA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "async": "^3.2.6", + "filelist": "^1.0.4", + "picocolors": "^1.1.1" + }, + "bin": { + "jake": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "devOptional": true, + "license": "MIT", + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, "node_modules/js-sha256": { "version": "0.11.1", "resolved": "https://registry.npmjs.org/js-sha256/-/js-sha256-0.11.1.tgz", @@ -6037,6 +8448,13 @@ "dev": true, "license": "MIT" }, + "node_modules/json-schema": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", + "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", + "dev": true, + "license": "(AFL-2.1 OR BSD-3-Clause)" + }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -6064,6 +8482,29 @@ "node": ">=6" } }, + "node_modules/jsonfile": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonpointer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-5.0.1.tgz", + "integrity": "sha512-p/nXbhSEcu3pZRdkW1OfJhpsVtW1gd4Wa1fnQc9YLiTfAjn0312eMKimbdIQzuZl9aa9xUGaRlP9T/CJE/ditQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/jsx-ast-utils": { "version": "3.3.5", "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", @@ -6099,6 +8540,16 @@ "node": ">= 8" } }, + "node_modules/leven": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", + "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -6144,6 +8595,20 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", + "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", + "dev": true, + "license": "MIT" + }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -6151,6 +8616,13 @@ "dev": true, "license": "MIT" }, + "node_modules/lodash.sortby": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "dev": true, + "license": "MIT" + }, "node_modules/loose-envify": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", @@ -6274,6 +8746,16 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", @@ -6328,9 +8810,9 @@ } }, "node_modules/node-releases": { - "version": "2.0.21", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.21.tgz", - "integrity": "sha512-5b0pgg78U3hwXkCM8Z9b2FJdPZlr9Psr9V2gQPESdGHqbntyFJKFW4r5TeWGFzafGY3hzs1JC62VEQMbl1JFkw==", + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", "dev": true, "license": "MIT" }, @@ -6530,6 +9012,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -6570,6 +9059,33 @@ "dev": true, "license": "MIT" }, + "node_modules/path-scurry": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.1.tgz", + "integrity": "sha512-oWyT4gICAu+kaA7QWk/jvCHWarMKNs6pXOGWKDTr7cw4IGcUbW+PeTfbaQiLGheFRpjo6O9J0PmyMfQPjH71oA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^11.0.0", + "minipass": "^7.1.2" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "11.2.4", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.2.4.tgz", + "integrity": "sha512-B5Y16Jr9LB9dHVkh6ZevG+vAbOsNOYCX+sXvFWFu7B3Iz5mijW3zdbMyhsh8ANd2mSWBYdJgnqi+mL7/LrOPYg==", + "dev": true, + "license": "BlueOak-1.0.0", + "engines": { + "node": "20 || >=22" + } + }, "node_modules/pathe": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", @@ -6806,6 +9322,19 @@ "node": ">=6.0.0" } }, + "node_modules/pretty-bytes": { + "version": "6.1.1", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-6.1.1.tgz", + "integrity": "sha512-mQUvGU6aUFQ+rNvTIAcZuWGRT9a6f6Yrg9bHs4ImKF+HZCEK+plBvnAZYSIQztknZF2qnzNtr6F8s0+IuptdlQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/prop-types": { "version": "15.8.1", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", @@ -7031,6 +9560,23 @@ "node": ">=6" } }, + "node_modules/quansync": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/quansync/-/quansync-1.0.0.tgz", + "integrity": "sha512-5xZacEEufv3HSTPQuchrvV6soaiACMFnq1H8wkVioctoH3TRha9Sz66lOxRwPK/qZj7HPiSveih9yAyh98gvqA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/antfu" + }, + { + "type": "individual", + "url": "https://github.com/sponsors/sxzz" + } + ], + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -7052,6 +9598,16 @@ ], "license": "MIT" }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, "node_modules/react": { "version": "19.1.1", "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", @@ -7295,6 +9851,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "dev": true, + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.2", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz", + "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/regexp.prototype.flags": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", @@ -7316,6 +9892,54 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/regexpu-core": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz", + "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==", + "dev": true, + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.2.2", + "regjsgen": "^0.8.0", + "regjsparser": "^0.13.0", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.2.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/regjsparser": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", + "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~3.1.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve": { "version": "1.22.10", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", @@ -7449,6 +10073,27 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, "node_modules/safe-push-apply": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", @@ -7524,6 +10169,16 @@ "node": ">=10" } }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/set-cookie-parser": { "version": "2.7.1", "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", @@ -7579,6 +10234,58 @@ "node": ">= 0.4" } }, + "node_modules/sharp": { + "version": "0.33.5", + "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", + "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", + "dev": true, + "hasInstallScript": true, + "license": "Apache-2.0", + "dependencies": { + "color": "^4.2.3", + "detect-libc": "^2.0.3", + "semver": "^7.6.3" + }, + "engines": { + "node": "^18.17.0 || ^20.3.0 || >=21.0.0" + }, + "funding": { + "url": "https://opencollective.com/libvips" + }, + "optionalDependencies": { + "@img/sharp-darwin-arm64": "0.33.5", + "@img/sharp-darwin-x64": "0.33.5", + "@img/sharp-libvips-darwin-arm64": "1.0.4", + "@img/sharp-libvips-darwin-x64": "1.0.4", + "@img/sharp-libvips-linux-arm": "1.0.5", + "@img/sharp-libvips-linux-arm64": "1.0.4", + "@img/sharp-libvips-linux-s390x": "1.0.4", + "@img/sharp-libvips-linux-x64": "1.0.4", + "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", + "@img/sharp-libvips-linuxmusl-x64": "1.0.4", + "@img/sharp-linux-arm": "0.33.5", + "@img/sharp-linux-arm64": "0.33.5", + "@img/sharp-linux-s390x": "0.33.5", + "@img/sharp-linux-x64": "0.33.5", + "@img/sharp-linuxmusl-arm64": "0.33.5", + "@img/sharp-linuxmusl-x64": "0.33.5", + "@img/sharp-wasm32": "0.33.5", + "@img/sharp-win32-ia32": "0.33.5", + "@img/sharp-win32-x64": "0.33.5" + } + }, + "node_modules/sharp-ico": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/sharp-ico/-/sharp-ico-0.1.5.tgz", + "integrity": "sha512-a3jODQl82NPp1d5OYb0wY+oFaPk7AvyxipIowCHk7pBsZCWgbe0yAkU2OOXdoH0ENyANhyOQbs9xkAiRHcF02Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "decode-ico": "*", + "ico-endec": "*", + "sharp": "*" + } + }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -7684,6 +10391,29 @@ "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", "license": "ISC" }, + "node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-swizzle": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", + "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, "node_modules/slugify": { "version": "1.6.6", "resolved": "https://registry.npmjs.org/slugify/-/slugify-1.6.6.tgz", @@ -7693,6 +10423,27 @@ "node": ">=8.0.0" } }, + "node_modules/smob": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", + "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==", + "dev": true, + "license": "MIT" + }, + "node_modules/source-map": { + "version": "0.8.0-beta.0", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.8.0-beta.0.tgz", + "integrity": "sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==", + "deprecated": "The work that was done in this beta branch won't be included in future versions", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "whatwg-url": "^7.0.0" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/source-map-js": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", @@ -7702,6 +10453,35 @@ "node": ">=0.10.0" } }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "devOptional": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/sourcemap-codec": { + "version": "1.4.8", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.8.tgz", + "integrity": "sha512-9NykojV5Uih4lgo5So5dtw+f0JgJX30KCNI8gwhz2J9A15wD0Ml6tjHKwf6fTSa6fAdVBdZeNOs9eJ71qCk8vA==", + "deprecated": "Please use @jridgewell/sourcemap-codec instead", + "dev": true, + "license": "MIT" + }, "node_modules/stackback": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", @@ -7728,6 +10508,70 @@ "node": ">= 0.4" } }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/string.prototype.matchall": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", @@ -7826,6 +10670,61 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/stringify-object": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", + "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "get-own-enumerable-property-symbols": "^3.0.0", + "is-obj": "^1.0.1", + "is-regexp": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", + "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", @@ -7836,6 +10735,16 @@ "node": ">=4" } }, + "node_modules/strip-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-comments/-/strip-comments-2.0.1.tgz", + "integrity": "sha512-ZprKx+bBLXv067WTCALv8SSz5l2+XhpYCsVtSqlMnkAXMWDq+/ekVbl1ghqP9rUHTzv6sm/DwCOiYutU/yp1fw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, "node_modules/strip-json-comments": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", @@ -7938,6 +10847,67 @@ "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", "license": "MIT" }, + "node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/tempy": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tempy/-/tempy-0.6.0.tgz", + "integrity": "sha512-G13vtMYPT/J8A4X2SjdtBTphZlrp1gKv6hZiOjw14RCWg6GbHuQBGtjlx75xLbYV/wEc0D7G5K4rxKP/cXk8Bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-stream": "^2.0.0", + "temp-dir": "^2.0.0", + "type-fest": "^0.16.0", + "unique-string": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/tempy/node_modules/type-fest": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.16.0.tgz", + "integrity": "sha512-eaBzG6MxNzEn9kiwvtre90cXaNLkmadMWa1zQMs3XORCXNbsH/OewwbxC5ia9dCxIxnTAsSxXJaa/p5y8DlvJg==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/terser": { + "version": "5.44.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", + "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", + "devOptional": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/tinybench": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", @@ -8022,6 +10992,13 @@ "node": ">=14.0.0" } }, + "node_modules/to-data-view": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/to-data-view/-/to-data-view-1.1.0.tgz", + "integrity": "sha512-1eAdufMg6mwgmlojAx3QeMnzB/BTVp7Tbndi3U7ftcT2zCZadjxkkmLmd97zmaxWi+sgGcgWrokmpEoy0Dn0vQ==", + "dev": true, + "license": "MIT" + }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -8035,6 +11012,16 @@ "node": ">=8.0" } }, + "node_modules/tr46": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-1.0.1.tgz", + "integrity": "sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "punycode": "^2.1.0" + } + }, "node_modules/ts-api-utils": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", @@ -8246,6 +11233,37 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/unconfig": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/unconfig/-/unconfig-7.4.2.tgz", + "integrity": "sha512-nrMlWRQ1xdTjSnSUqvYqJzbTBFugoqHobQj58B2bc8qxHKBBHMNNsWQFP3Cd3/JZK907voM2geYPWqD4VK3MPQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@quansync/fs": "^1.0.0", + "defu": "^6.1.4", + "jiti": "^2.6.1", + "quansync": "^1.0.0", + "unconfig-core": "7.4.2" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, + "node_modules/unconfig-core": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/unconfig-core/-/unconfig-core-7.4.2.tgz", + "integrity": "sha512-VgPCvLWugINbXvMQDf8Jh0mlbvNjNC6eSUziHsBCMpxR05OPrNrvDnyatdMjRgcHaaNsCqz+wjNXxNw1kRLHUg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@quansync/fs": "^1.0.0", + "quansync": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/undici-types": { "version": "7.12.0", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.12.0.tgz", @@ -8253,10 +11271,88 @@ "devOptional": true, "license": "MIT" }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz", + "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz", + "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unique-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unique-string/-/unique-string-2.0.0.tgz", + "integrity": "sha512-uNaeirEPvpZWSgzwsPGtU2zVSTrn/8L5q/IexZmH0eH6SA73CmAA5U4GwORTxQAZs95TAXLNqeLoPPNO5gZfWg==", + "dev": true, + "license": "MIT", + "dependencies": { + "crypto-random-string": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/upath": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz", + "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4", + "yarn": "*" + } + }, "node_modules/update-browserslist-db": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz", - "integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==", + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", "dev": true, "funding": [ { @@ -8507,6 +11603,37 @@ "url": "https://opencollective.com/vitest" } }, + "node_modules/vite-plugin-pwa": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vite-plugin-pwa/-/vite-plugin-pwa-1.2.0.tgz", + "integrity": "sha512-a2xld+SJshT9Lgcv8Ji4+srFJL4k/1bVbd1x06JIkvecpQkwkvCncD1+gSzcdm3s+owWLpMJerG3aN5jupJEVw==", + "dev": true, + "license": "MIT", + "dependencies": { + "debug": "^4.3.6", + "pretty-bytes": "^6.1.1", + "tinyglobby": "^0.2.10", + "workbox-build": "^7.4.0", + "workbox-window": "^7.4.0" + }, + "engines": { + "node": ">=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "@vite-pwa/assets-generator": "^1.0.0", + "vite": "^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0", + "workbox-build": "^7.4.0", + "workbox-window": "^7.4.0" + }, + "peerDependenciesMeta": { + "@vite-pwa/assets-generator": { + "optional": true + } + } + }, "node_modules/vite-plugin-top-level-await": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/vite-plugin-top-level-await/-/vite-plugin-top-level-await-1.6.0.tgz", @@ -8663,6 +11790,25 @@ "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", "license": "MIT" }, + "node_modules/webidl-conversions": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", + "integrity": "sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-url": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-7.1.0.tgz", + "integrity": "sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash.sortby": "^4.7.0", + "tr46": "^1.0.1", + "webidl-conversions": "^4.0.2" + } + }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -8794,6 +11940,459 @@ "node": ">=0.10.0" } }, + "node_modules/workbox-background-sync": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-background-sync/-/workbox-background-sync-7.4.0.tgz", + "integrity": "sha512-8CB9OxKAgKZKyNMwfGZ1XESx89GryWTfI+V5yEj8sHjFH8MFelUwYXEyldEK6M6oKMmn807GoJFUEA1sC4XS9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "7.4.0" + } + }, + "node_modules/workbox-broadcast-update": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-broadcast-update/-/workbox-broadcast-update-7.4.0.tgz", + "integrity": "sha512-+eZQwoktlvo62cI0b+QBr40v5XjighxPq3Fzo9AWMiAosmpG5gxRHgTbGGhaJv/q/MFVxwFNGh/UwHZ/8K88lA==", + "dev": true, + "license": "MIT", + "dependencies": { + "workbox-core": "7.4.0" + } + }, + "node_modules/workbox-build": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-build/-/workbox-build-7.4.0.tgz", + "integrity": "sha512-Ntk1pWb0caOFIvwz/hfgrov/OJ45wPEhI5PbTywQcYjyZiVhT3UrwwUPl6TRYbTm4moaFYithYnl1lvZ8UjxcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@apideck/better-ajv-errors": "^0.3.1", + "@babel/core": "^7.24.4", + "@babel/preset-env": "^7.11.0", + "@babel/runtime": "^7.11.2", + "@rollup/plugin-babel": "^5.2.0", + "@rollup/plugin-node-resolve": "^15.2.3", + "@rollup/plugin-replace": "^2.4.1", + "@rollup/plugin-terser": "^0.4.3", + "@surma/rollup-plugin-off-main-thread": "^2.2.3", + "ajv": "^8.6.0", + "common-tags": "^1.8.0", + "fast-json-stable-stringify": "^2.1.0", + "fs-extra": "^9.0.1", + "glob": "^11.0.1", + "lodash": "^4.17.20", + "pretty-bytes": "^5.3.0", + "rollup": "^2.79.2", + "source-map": "^0.8.0-beta.0", + "stringify-object": "^3.3.0", + "strip-comments": "^2.0.1", + "tempy": "^0.6.0", + "upath": "^1.2.0", + "workbox-background-sync": "7.4.0", + "workbox-broadcast-update": "7.4.0", + "workbox-cacheable-response": "7.4.0", + "workbox-core": "7.4.0", + "workbox-expiration": "7.4.0", + "workbox-google-analytics": "7.4.0", + "workbox-navigation-preload": "7.4.0", + "workbox-precaching": "7.4.0", + "workbox-range-requests": "7.4.0", + "workbox-recipes": "7.4.0", + "workbox-routing": "7.4.0", + "workbox-strategies": "7.4.0", + "workbox-streams": "7.4.0", + "workbox-sw": "7.4.0", + "workbox-window": "7.4.0" + }, + "engines": { + "node": ">=20.0.0" + } + }, + "node_modules/workbox-build/node_modules/@apideck/better-ajv-errors": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@apideck/better-ajv-errors/-/better-ajv-errors-0.3.6.tgz", + "integrity": "sha512-P+ZygBLZtkp0qqOAJJVX4oX/sFo5JR3eBWwwuqHHhK0GIgQOKWrAfiAaWX0aArHkRWHMuggFEgAZNxVPwPZYaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-schema": "^0.4.0", + "jsonpointer": "^5.0.0", + "leven": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "ajv": ">=8" + } + }, + "node_modules/workbox-build/node_modules/@rollup/plugin-babel": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz", + "integrity": "sha512-WFfdLWU/xVWKeRQnKmIAQULUI7Il0gZnBIH/ZFO069wYIfPu+8zrfp/KMW0atmELoRDq8FbiP3VCss9MhCut7Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.10.4", + "@rollup/pluginutils": "^3.1.0" + }, + "engines": { + "node": ">= 10.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0", + "@types/babel__core": "^7.1.9", + "rollup": "^1.20.0||^2.0.0" + }, + "peerDependenciesMeta": { + "@types/babel__core": { + "optional": true + } + } + }, + "node_modules/workbox-build/node_modules/@rollup/plugin-replace": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-2.4.2.tgz", + "integrity": "sha512-IGcu+cydlUMZ5En85jxHH4qj2hta/11BHq95iHEyb2sbgiN0eCdzvUcHw5gt9pBL5lTi4JDYJ1acCoMGpTvEZg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@rollup/pluginutils": "^3.1.0", + "magic-string": "^0.25.7" + }, + "peerDependencies": { + "rollup": "^1.20.0 || ^2.0.0" + } + }, + "node_modules/workbox-build/node_modules/@rollup/pluginutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.1.0.tgz", + "integrity": "sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "0.0.39", + "estree-walker": "^1.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0" + } + }, + "node_modules/workbox-build/node_modules/@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==", + "dev": true, + "license": "MIT" + }, + "node_modules/workbox-build/node_modules/ajv": { + "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, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3", + "fast-uri": "^3.0.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/workbox-build/node_modules/estree-walker": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz", + "integrity": "sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==", + "dev": true, + "license": "MIT" + }, + "node_modules/workbox-build/node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, + "node_modules/workbox-build/node_modules/magic-string": { + "version": "0.25.9", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz", + "integrity": "sha512-RmF0AsMzgt25qzqqLc1+MbHmhdx0ojF2Fvs4XnOqz2ZOBXzzkEwc/dJQZCYHAn7v1jbVOjAZfK8msRn4BxO4VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "sourcemap-codec": "^1.4.8" + } + }, + "node_modules/workbox-build/node_modules/pretty-bytes": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", + "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/workbox-build/node_modules/rollup": { + "version": "2.79.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-2.79.2.tgz", + "integrity": "sha512-fS6iqSPZDs3dr/y7Od6y5nha8dW1YnbgtsyotCVvoFGKbERG++CVRFv1meyGDE1SNItQA8BrnCw7ScdAhRJ3XQ==", + "dev": true, + "license": "MIT", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=10.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/workbox-cacheable-response": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-cacheable-response/-/workbox-cacheable-response-7.4.0.tgz", + "integrity": "sha512-0Fb8795zg/x23ISFkAc7lbWes6vbw34DGFIMw31cwuHPgDEC/5EYm6m/ZkylLX0EnEbbOyOCLjKgFS/Z5g0HeQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "workbox-core": "7.4.0" + } + }, + "node_modules/workbox-core": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-core/-/workbox-core-7.4.0.tgz", + "integrity": "sha512-6BMfd8tYEnN4baG4emG9U0hdXM4gGuDU3ectXuVHnj71vwxTFI7WOpQJC4siTOlVtGqCUtj0ZQNsrvi6kZZTAQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/workbox-expiration": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-expiration/-/workbox-expiration-7.4.0.tgz", + "integrity": "sha512-V50p4BxYhtA80eOvulu8xVfPBgZbkxJ1Jr8UUn0rvqjGhLDqKNtfrDfjJKnLz2U8fO2xGQJTx/SKXNTzHOjnHw==", + "dev": true, + "license": "MIT", + "dependencies": { + "idb": "^7.0.1", + "workbox-core": "7.4.0" + } + }, + "node_modules/workbox-google-analytics": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-google-analytics/-/workbox-google-analytics-7.4.0.tgz", + "integrity": "sha512-MVPXQslRF6YHkzGoFw1A4GIB8GrKym/A5+jYDUSL+AeJw4ytQGrozYdiZqUW1TPQHW8isBCBtyFJergUXyNoWQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "workbox-background-sync": "7.4.0", + "workbox-core": "7.4.0", + "workbox-routing": "7.4.0", + "workbox-strategies": "7.4.0" + } + }, + "node_modules/workbox-navigation-preload": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-navigation-preload/-/workbox-navigation-preload-7.4.0.tgz", + "integrity": "sha512-etzftSgdQfjMcfPgbfaZCfM2QuR1P+4o8uCA2s4rf3chtKTq/Om7g/qvEOcZkG6v7JZOSOxVYQiOu6PbAZgU6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "workbox-core": "7.4.0" + } + }, + "node_modules/workbox-precaching": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-precaching/-/workbox-precaching-7.4.0.tgz", + "integrity": "sha512-VQs37T6jDqf1rTxUJZXRl3yjZMf5JX/vDPhmx2CPgDDKXATzEoqyRqhYnRoxl6Kr0rqaQlp32i9rtG5zTzIlNg==", + "dev": true, + "license": "MIT", + "dependencies": { + "workbox-core": "7.4.0", + "workbox-routing": "7.4.0", + "workbox-strategies": "7.4.0" + } + }, + "node_modules/workbox-range-requests": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-range-requests/-/workbox-range-requests-7.4.0.tgz", + "integrity": "sha512-3Vq854ZNuP6Y0KZOQWLaLC9FfM7ZaE+iuQl4VhADXybwzr4z/sMmnLgTeUZLq5PaDlcJBxYXQ3U91V7dwAIfvw==", + "dev": true, + "license": "MIT", + "dependencies": { + "workbox-core": "7.4.0" + } + }, + "node_modules/workbox-recipes": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-recipes/-/workbox-recipes-7.4.0.tgz", + "integrity": "sha512-kOkWvsAn4H8GvAkwfJTbwINdv4voFoiE9hbezgB1sb/0NLyTG4rE7l6LvS8lLk5QIRIto+DjXLuAuG3Vmt3cxQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "workbox-cacheable-response": "7.4.0", + "workbox-core": "7.4.0", + "workbox-expiration": "7.4.0", + "workbox-precaching": "7.4.0", + "workbox-routing": "7.4.0", + "workbox-strategies": "7.4.0" + } + }, + "node_modules/workbox-routing": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-routing/-/workbox-routing-7.4.0.tgz", + "integrity": "sha512-C/ooj5uBWYAhAqwmU8HYQJdOjjDKBp9MzTQ+otpMmd+q0eF59K+NuXUek34wbL0RFrIXe/KKT+tUWcZcBqxbHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "workbox-core": "7.4.0" + } + }, + "node_modules/workbox-strategies": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-strategies/-/workbox-strategies-7.4.0.tgz", + "integrity": "sha512-T4hVqIi5A4mHi92+5EppMX3cLaVywDp8nsyUgJhOZxcfSV/eQofcOA6/EMo5rnTNmNTpw0rUgjAI6LaVullPpg==", + "dev": true, + "license": "MIT", + "dependencies": { + "workbox-core": "7.4.0" + } + }, + "node_modules/workbox-streams": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-streams/-/workbox-streams-7.4.0.tgz", + "integrity": "sha512-QHPBQrey7hQbnTs5GrEVoWz7RhHJXnPT+12qqWM378orDMo5VMJLCkCM1cnCk+8Eq92lccx/VgRZ7WAzZWbSLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "workbox-core": "7.4.0", + "workbox-routing": "7.4.0" + } + }, + "node_modules/workbox-sw": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-sw/-/workbox-sw-7.4.0.tgz", + "integrity": "sha512-ltU+Kr3qWR6BtbdlMnCjobZKzeV1hN+S6UvDywBrwM19TTyqA03X66dzw1tEIdJvQ4lYKkBFox6IAEhoSEZ8Xw==", + "dev": true, + "license": "MIT" + }, + "node_modules/workbox-window": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/workbox-window/-/workbox-window-7.4.0.tgz", + "integrity": "sha512-/bIYdBLAVsNR3v7gYGaV4pQW3M3kEPx5E8vDxGvxo6khTrGtSSCS7QiFKv9ogzBgZiy0OXLP9zO28U/1nF1mfw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/trusted-types": "^2.0.2", + "workbox-core": "7.4.0" + } + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true, + "license": "MIT" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", + "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/ws": { "version": "8.18.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", diff --git a/package.json b/package.json index 17284d21..dcfa5bca 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "@types/react-router-dom": "5.3.3", "@typescript-eslint/eslint-plugin": "8.44.1", "@typescript-eslint/parser": "8.44.1", + "@vite-pwa/assets-generator": "^1.0.2", "@vitejs/plugin-react": "5.0.3", "eslint": "9.36.0", "eslint-config-prettier": "10.1.8", @@ -86,7 +87,8 @@ "sugarss": "5.0.1", "typescript": "5.9.2", "typescript-eslint": "8.44.1", - "vite": "7.1.7" + "vite": "7.1.7", + "vite-plugin-pwa": "^1.2.0" }, "engines": { "node": "22.19.0" diff --git a/public/apple-touch-icon-180x180.png b/public/apple-touch-icon-180x180.png new file mode 100644 index 0000000000000000000000000000000000000000..e3043f1bc2ba5fc7b35d700eeb0b7af295889e47 GIT binary patch literal 1190 zcmV;X1X=ruP)+bs) zG_4Xd!X7o4FG1aUVgEu&=Kufy`1t)8H_{|EfmKoNDmH3pS@+%G_mq+Ky1(#VZ`oL4 zmzSW%YIwt){*y8Q000SaNLh0L00Za%00Za&wR=))000CHNkl2kCx5C&kx zC8I_b_5QE*Fe(ZPexq@qIo17ps`AvER#6u6lVA}d{uo3O}<#) zLK6Z+O`w>sbO?#x&)3xijQN6^0BMd(ZB5_={dv>`P|zPoO#lV`an$62pqZ{vQIo$0 zEo4zoMX3xG^&inp7OECCFtqoN$m(q_9!r`8K=bO2)={T{7Hw5+Q3FH!TAIJn)f%-7 zb<_J3x@%jrKhi+A?HYBF5?XilR6LRPu%doI9RS^}Q9pIp3x_r@Mg|{!h?>?S6|@nx zdYUuP=+YH6rP;`mKwDAMEE@$}v@7cRjn4AC7qHRoG3q?e2dLNUe0vMXw>d}R! z869Dv=Yg|!d(f&r?~*WRgKeQ}6P@Ruz7l*NT~lhhok?d@_s>V4Z~~y~+EkwOmg z47BN%-k#3%1OK0IyP?o)lW4T4teb~6=kpNdJnrwmjq6Vai(8|aKj~={+YeFEg~eW{ z0r;s|RpY%VgP;w!G0nVF=lV)C-p(SUSGFN&H zdWXKXpfDI(w}^?(Z!X;ov!iHzaW&EXtwmR%b`)7|-423**ijT{XWz3M&eGi4m*ghO zG`FiJxiL7+E!atJcK?2Z{NMo&NgtJw=Ak5M9{-Z&K|6^aX_V;UQHdVY^@FFlAsW$$ zMl_-kjc7z88qtVGG@=oWXhb6#(TGMgq7jW~M4RaU0OEg_V;d5FWB>pF07*qoM6N<$ Ef;3e~yZ`_I literal 0 HcmV?d00001 diff --git a/public/favicon.ico b/public/favicon.ico new file mode 100644 index 0000000000000000000000000000000000000000..f1e2124468cda1eb93388edfbdff6aa703326ded GIT binary patch literal 846 zcmV-U1F`%70096205C8B0096905}5x02TlM0EtjeM-2)Z3IG5A4M|8uQUCw|FaQ7m zFbD-Jgcuv_C98EH~V#_cp!wko#!|6zBA9w=B(1=T$Ytf+JJQmQ2I{*T=(aw zaF2?P+k6m}gnLxPI7R`2hkJhA@qCI=b&T5=z*mpXIG%6EY@9-};p4;rDKSsH8r>k; zmyPEyr@%N#TGj>-hmDH|qWLQYrileV@TCRdcz#*+z@6P6^rZZSZrnVeOSiWJy;^sp z1}WnI)S9fW6;v=0ce24?U)&=OgW!6^xVCEA5sO$BB*W6bDOy4fc)CE! zRXAUGnNEP}i}!SE_IZo&f9yoEOqP)_36LLOYSEkZ?MRx}i2`8c^0Pph1gNa+1r5p& z3?c&{Wcq{-b)o=gI$p@DVfWLJB@_%=*$*GDG z#3%rtyfR2QPNPKdS*(T%AV0pOjN`@tFc9JcM+k=LW&kiKy=yaXj{!_hRp{RRjUbjF zqQn}fIR`O_&JP-#3jl#>e#YWlBYpr5axzFK127FZ9BjN|3_hI%01hQiqbwK+A695e zq*2sA8XbLtQtJe;qu5rB0bn2iu-JeMzbzQ{IqwHR({ zl$1QXXyQI+n|i)l%>3o9mG$d&YY<*=SXqC?WDUYgK5I~3vsx)vE@=bSDL^TC6a4`E Y2C{Pr_*ut%D*ylh07*qoM6N<$g3uRiX8-^I literal 0 HcmV?d00001 diff --git a/public/favicon.png b/public/favicon.png deleted file mode 100644 index 4b2b06d16c2595f47159d2063b02dcfd80bc1da4..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3097 zcmV+!4CeERP)!n75xB8iW>R+Fr;X)Pa?AF$BeN+ll-edOR}Z?v?23-8sG^{dYU%llQY>SR*G z5K!m~uTGJgLBld@wa2J?D6K=E**TAt5LiB_VQ@f0M_dUB3Pi0}b922?%@nQnE_way zU|AmCe#gNRPg&UiYyqkgc*OIXBSi}<#hP*l*51$++O>7x0;O<{#k$_ng|RSf{_*u3C8-&tc#m}*pJao37q)Ifv$_DldxB0 z-?BNl?_w#(iGy>;)U=C{vkZLyJ89f;XGSUzZPhHqxVQ2i&KZee*Uq%;+)8+cS(@Sj zWjJwgS_Mx+Z!tZ@0#9c=T(~)g^PVzs=x`Cqgi?(Mp1ukpp14RDzkF*FiH@KnLn$h} zMm>s@EgpOzgIE8PgG0m2T6tW5bw9qiwi`Lik=|I$#=~vh634+q#gH(NT41Fq|nzuY%s(YR|j|` zTRJTWwgSg3U#9X%7V^vRpoKvf&8_H{7q*N*%G6O(2x3AdVJTK9fSx`ui=A7$5Hl3H zerVd_z(|yh%~scB77DGyeuPT2b-xJKKAj>srfM{xOMhv_bXD}G4g6;B6lQWI-1U%6Q6#+C^y%-?@yCZV7<=Pm-1N;Q*mlt} z$`}S^HfK>YlVANUYFTK$aVK3#!oyfyXQAMeca$!Sz4#Fx z=^w|pzqSs(g+*^osYLr8v}_96`SXYb&Qgj2r$D2WH8SU)JeXMy7Y1xEjS>Z|=j)&qf#Sd=Ayr8;Sm4K>$YJG59V4sQOTZj) ze1{ez_5UP%ev`io$U?!)9!wIsn*ukuhF>aQ>p_~O#b)n53vV9H;rxvTK`TWRBZW@# zO3rd6#F(ahqPS=x==_7Y+^Do5fqTdU9zm)=-`I4`Iav?pph=R+0RQ_Q&*Fhcj$_@3 z!0s!$amAKF3@z&b#Xj--l3Z04MOnC4{9qnYC37cJ6ScJE`6g_iJ>b%Jq=0YJwMy4U z^<9_gE|sU9DT?}nf>++m;-y!|anEnZNQoubwS6U4pFJocm&>_SzB*+^7VZ_Twx+dj zl|WZ%9T1{Z5;)f{(l}uB;Mq1v;(D)7cE}fAAITedr)IuItB@ zSFFZ`o6e@H%S4_MfK9GBnG$|vlVw3vf;%%0>W;+`*L~!DgZvPun9wDJxMt;=mh0JP z4rh^9TzCpS;qdT-k}yH(SGYy|{ooP&^T1)8_30j5cFB3zv26ne2l_~Px4jY}K_vkV zf7f1#fTfzmWqZsRVkU*K(8&5OEQJZQF1dR?=i!>GQ#fN-#l9z}vH#G=I5BCH;x^J9 zzEp(eOC{q3ydsW$@DA>{YmAVX#0@uWr9#SSD5RpYhrOUReWRuFJ}JN+h`}TU4B^NW zT8asx7z!%1oNIz@RN3+8-S?JY|MQc0^yy<5d+jLI+d+8y*jS@>JYyB^&z}< zY&9O(`z9WG_+4}vr(sF*O!RdOKq)FTw%1@Rf!0uJ!G+qmfXhyf0gV-iK{H%Zz?BNP zQUN7^2OtBNVUSMgas%Ll2^%lJZsCQo68?Q;7=4K|kg zlNvTeB~IRCj*qhf#C7TvP-UURjji6%p;Jb2@XUet@z>`vc>17^i4Tc}6B+DF8t6@$ zlxjV4mO*i2z$q!{>q?m)37I;*ypMIC2i9()gq*L{ z;<_+fLMTEd0<^V}y{dsrD`@{RvT%xWc2Q78rqa5saA1%EobxHLX+7I>-y;N+G-rj>tE=*$SpeA?mm~Jzjk_RUzVG-3m(MZ!OyXry-cINVgNu`|^Y@lzck6qWh zc<6o=GgE=}YJ&^%f{m%^90r!FxN7@yd}YTlE;u(Ocl>fht$DXui1`c7@9}0^o)l&| z!yCMk%=scnd%P7g{(+4Z!-hO;Xg0W1l!EPy&-l3ZW(Q->DR|>B(9v%hq(DHu# z_Wou<0l;1pR2-fzNyAq$s`rerQx zT41T71PAk$T^=@EMu>GeuptBa_FKMz&a^I#keMk-OQ}-ug|ki0e9W(294ioW_0ZL& z%AGn9rV^|P3y`Ej{jvSCxOR6JmJI{~C@ofYR)V2p%?2*k^a@802AGX?Jbbryg6OHQ88F-oGSjvTX+#a%&_l!D*y%Mgbt;l}IwFtXAt$4J2IPt`FQ z&mmW7x*mVOg!_IsgD3Y}ByXO}bsKAfFj5++MC4)c9cLm@6}E1;h-Cs&{lI8prJEW! z1f%*Oj*Q))P^fQ(f`rBj)&YdxiQHG;5uvdo_s!%8Z5}qnR_%zX1&qS?6`?Etl2Cip n{2wu*t(k|T)3to3#W?>1l1m`rE&=M|00000NkvXXu0mjfhQ`*F diff --git a/public/icon512_maskable.png b/public/icon512_maskable.png deleted file mode 100644 index e123145edccbeeaebd0d2fb6811a09f3299ca878..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 73407 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 L)XC>3aCiR)aDGM8 diff --git a/public/icon512_rounded.png b/public/icon512_rounded.png deleted file mode 100644 index 0755aabe91c0d5699c3ff581e057465b36ca02a1..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 60626 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 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/public/manifest.json b/public/manifest.json index 0cd56001..ba799e8c 100644 --- a/public/manifest.json +++ b/public/manifest.json @@ -3,16 +3,25 @@ "background_color": "#0F33CE", "icons": [ { - "purpose": "maskable", - "sizes": "512x512", - "src": "icon512_maskable.png", + "src": "pwa-64x64.png", + "sizes": "64x64", + "type": "image/png" + }, + { + "src": "pwa-192x192.png", + "sizes": "192x192", "type": "image/png" }, { - "purpose": "any", + "src": "pwa-512x512.png", "sizes": "512x512", - "src": "icon512_rounded.png", "type": "image/png" + }, + { + "src": "maskable-icon-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" } ], "orientation": "any", @@ -25,4 +34,4 @@ "description": "Manage test planning, execution and report", "scope": "/", "start_url": "/?source=pwa" -} +} \ No newline at end of file diff --git a/public/maskable-icon-512x512.png b/public/maskable-icon-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..8434b0eca667c7d75b1cd71565714d8e47cdbf8b GIT binary patch literal 5083 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 d_20O0bL literal 0 HcmV?d00001 diff --git a/public/pwa-512x512.png b/public/pwa-512x512.png new file mode 100644 index 0000000000000000000000000000000000000000..183f66b02bd100289c1a7d088d0784634b07f7ee GIT binary patch literal 7408 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 literal 0 HcmV?d00001 diff --git a/vite.config.js b/vite.config.js index 00b42a46..953c56e1 100644 --- a/vite.config.js +++ b/vite.config.js @@ -1,11 +1,40 @@ -import path from "path"; import react from "@vitejs/plugin-react"; +import path from "path"; import { defineConfig } from "vite"; +import { VitePWA } from "vite-plugin-pwa"; import topLevelAwait from "vite-plugin-top-level-await"; import wasm from "vite-plugin-wasm"; export default defineConfig({ - plugins: [topLevelAwait(), wasm(), react()], + plugins: [topLevelAwait(), wasm(), react(), VitePWA({ + registerType: "autoUpdate", + devOptions: { + enabled: true + }, + manifest: { + name: "yTestbook", + short_name: "yTestbook", + start_url: "/", + display: "standalone", + background_color: "#0f33ce", + theme_color: "#0f33ce", + orientation: "portrait-primary", + "icons": [ + { + "src": "/pwa-192x192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any" + }, + { + "src": "/pwa-512x512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any" + } + ] + } + })], worker: { format: "es", plugins: () => [wasm()], From c97fcfb126a0675d6bfe97925f38ba90a943f74e Mon Sep 17 00:00:00 2001 From: Alessandro Falezza Date: Mon, 22 Dec 2025 15:07:53 +0100 Subject: [PATCH 2/6] Fix type that causes build error --- src/components/stepDetails/StepLogNotes.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/stepDetails/StepLogNotes.tsx b/src/components/stepDetails/StepLogNotes.tsx index 4818dcef..d544dc31 100644 --- a/src/components/stepDetails/StepLogNotes.tsx +++ b/src/components/stepDetails/StepLogNotes.tsx @@ -1,9 +1,9 @@ -import { IconWindowMaximize } from "@tabler/icons-react"; import { ActionIcon, Button, Flex, Group, Text } from "@mantine/core"; import { modals } from "@mantine/modals"; +import { IconWindowMaximize } from "@tabler/icons-react"; interface IProps { - notes?: string; + notes?: string | null; } const NOTES_LIMIT_LENGTH = 10; From 4df374e173f478b5e7645b708c0367fd20daf942 Mon Sep 17 00:00:00 2001 From: Alessandro Falezza Date: Mon, 22 Dec 2025 15:08:20 +0100 Subject: [PATCH 3/6] Fine tune service worker --- public/manifest.json | 37 ------------------------------------- vite.config.js | 5 ++++- 2 files changed, 4 insertions(+), 38 deletions(-) delete mode 100644 public/manifest.json diff --git a/public/manifest.json b/public/manifest.json deleted file mode 100644 index ba799e8c..00000000 --- a/public/manifest.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "theme_color": "#0F33CE", - "background_color": "#0F33CE", - "icons": [ - { - "src": "pwa-64x64.png", - "sizes": "64x64", - "type": "image/png" - }, - { - "src": "pwa-192x192.png", - "sizes": "192x192", - "type": "image/png" - }, - { - "src": "pwa-512x512.png", - "sizes": "512x512", - "type": "image/png" - }, - { - "src": "maskable-icon-512x512.png", - "sizes": "512x512", - "type": "image/png", - "purpose": "maskable" - } - ], - "orientation": "any", - "display": "standalone", - "id": "/?source=pwa", - "dir": "auto", - "lang": "en", - "name": "yTestbook", - "short_name": "yTestbook", - "description": "Manage test planning, execution and report", - "scope": "/", - "start_url": "/?source=pwa" -} \ No newline at end of file diff --git a/vite.config.js b/vite.config.js index 953c56e1..11091788 100644 --- a/vite.config.js +++ b/vite.config.js @@ -7,10 +7,13 @@ import wasm from "vite-plugin-wasm"; export default defineConfig({ plugins: [topLevelAwait(), wasm(), react(), VitePWA({ - registerType: "autoUpdate", + registerType: "prompt", devOptions: { enabled: true }, + workbox: { + maximumFileSizeToCacheInBytes: 5 * 1024 * 1024 // 5MB + }, manifest: { name: "yTestbook", short_name: "yTestbook", From 57e973a5ecaa53a3a5dec7185a9d7db7c2bf6696 Mon Sep 17 00:00:00 2001 From: Alessandro Falezza Date: Mon, 22 Dec 2025 15:08:26 +0100 Subject: [PATCH 4/6] generate dev code --- dev-dist/registerSW.js | 1 + dev-dist/sw.js | 92 + dev-dist/workbox-5a5d9309.js | 3395 ++++++++++++++++++++++++++++++++++ 3 files changed, 3488 insertions(+) create mode 100644 dev-dist/registerSW.js create mode 100644 dev-dist/sw.js create mode 100644 dev-dist/workbox-5a5d9309.js diff --git a/dev-dist/registerSW.js b/dev-dist/registerSW.js new file mode 100644 index 00000000..1d5625f4 --- /dev/null +++ b/dev-dist/registerSW.js @@ -0,0 +1 @@ +if('serviceWorker' in navigator) navigator.serviceWorker.register('/dev-sw.js?dev-sw', { scope: '/', type: 'classic' }) \ No newline at end of file diff --git a/dev-dist/sw.js b/dev-dist/sw.js new file mode 100644 index 00000000..47374948 --- /dev/null +++ b/dev-dist/sw.js @@ -0,0 +1,92 @@ +/** + * Copyright 2018 Google Inc. All Rights Reserved. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +// If the loader is already loaded, just stop. +if (!self.define) { + let registry = {}; + + // Used for `eval` and `importScripts` where we can't get script URL by other means. + // In both cases, it's safe to use a global var because those functions are synchronous. + let nextDefineUri; + + const singleRequire = (uri, parentUri) => { + uri = new URL(uri + ".js", parentUri).href; + return registry[uri] || ( + + new Promise(resolve => { + if ("document" in self) { + const script = document.createElement("script"); + script.src = uri; + script.onload = resolve; + document.head.appendChild(script); + } else { + nextDefineUri = uri; + importScripts(uri); + resolve(); + } + }) + + .then(() => { + let promise = registry[uri]; + if (!promise) { + throw new Error(`Module ${uri} didn’t register its module`); + } + return promise; + }) + ); + }; + + self.define = (depsNames, factory) => { + const uri = nextDefineUri || ("document" in self ? document.currentScript.src : "") || location.href; + if (registry[uri]) { + // Module is already loading or loaded. + return; + } + let exports = {}; + const require = depUri => singleRequire(depUri, uri); + const specialDeps = { + module: { uri }, + exports, + require + }; + registry[uri] = Promise.all(depsNames.map( + depName => specialDeps[depName] || require(depName) + )).then(deps => { + factory(...deps); + return exports; + }); + }; +} +define(['./workbox-5a5d9309'], (function (workbox) { 'use strict'; + + self.skipWaiting(); + workbox.clientsClaim(); + + /** + * The precacheAndRoute() method efficiently caches and responds to + * requests for URLs in the manifest. + * See https://goo.gl/S9QRab + */ + workbox.precacheAndRoute([{ + "url": "registerSW.js", + "revision": "3ca0b8505b4bec776b69afdba2768812" + }, { + "url": "index.html", + "revision": "0.05d2ranheq8" + }], {}); + workbox.cleanupOutdatedCaches(); + workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), { + allowlist: [/^\/$/] + })); + +})); diff --git a/dev-dist/workbox-5a5d9309.js b/dev-dist/workbox-5a5d9309.js new file mode 100644 index 00000000..6f2a448e --- /dev/null +++ b/dev-dist/workbox-5a5d9309.js @@ -0,0 +1,3395 @@ +define(['exports'], (function (exports) { 'use strict'; + + // @ts-ignore + try { + self['workbox:core:7.3.0'] && _(); + } catch (e) {} + + /* + Copyright 2019 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * Claim any currently available clients once the service worker + * becomes active. This is normally used in conjunction with `skipWaiting()`. + * + * @memberof workbox-core + */ + function clientsClaim() { + self.addEventListener('activate', () => self.clients.claim()); + } + + /* + Copyright 2019 Google LLC + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + const logger = (() => { + // Don't overwrite this value if it's already set. + // See https://github.com/GoogleChrome/workbox/pull/2284#issuecomment-560470923 + if (!('__WB_DISABLE_DEV_LOGS' in globalThis)) { + self.__WB_DISABLE_DEV_LOGS = false; + } + let inGroup = false; + const methodToColorMap = { + debug: `#7f8c8d`, + log: `#2ecc71`, + warn: `#f39c12`, + error: `#c0392b`, + groupCollapsed: `#3498db`, + groupEnd: null // No colored prefix on groupEnd + }; + const print = function (method, args) { + if (self.__WB_DISABLE_DEV_LOGS) { + return; + } + if (method === 'groupCollapsed') { + // Safari doesn't print all console.groupCollapsed() arguments: + // https://bugs.webkit.org/show_bug.cgi?id=182754 + if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) { + console[method](...args); + return; + } + } + const styles = [`background: ${methodToColorMap[method]}`, `border-radius: 0.5em`, `color: white`, `font-weight: bold`, `padding: 2px 0.5em`]; + // When in a group, the workbox prefix is not displayed. + const logPrefix = inGroup ? [] : ['%cworkbox', styles.join(';')]; + console[method](...logPrefix, ...args); + if (method === 'groupCollapsed') { + inGroup = true; + } + if (method === 'groupEnd') { + inGroup = false; + } + }; + // eslint-disable-next-line @typescript-eslint/ban-types + const api = {}; + const loggerMethods = Object.keys(methodToColorMap); + for (const key of loggerMethods) { + const method = key; + api[method] = (...args) => { + print(method, args); + }; + } + return api; + })(); + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + const messages = { + 'invalid-value': ({ + paramName, + validValueDescription, + value + }) => { + if (!paramName || !validValueDescription) { + throw new Error(`Unexpected input to 'invalid-value' error.`); + } + return `The '${paramName}' parameter was given a value with an ` + `unexpected value. ${validValueDescription} Received a value of ` + `${JSON.stringify(value)}.`; + }, + 'not-an-array': ({ + moduleName, + className, + funcName, + paramName + }) => { + if (!moduleName || !className || !funcName || !paramName) { + throw new Error(`Unexpected input to 'not-an-array' error.`); + } + return `The parameter '${paramName}' passed into ` + `'${moduleName}.${className}.${funcName}()' must be an array.`; + }, + 'incorrect-type': ({ + expectedType, + paramName, + moduleName, + className, + funcName + }) => { + if (!expectedType || !paramName || !moduleName || !funcName) { + throw new Error(`Unexpected input to 'incorrect-type' error.`); + } + const classNameStr = className ? `${className}.` : ''; + return `The parameter '${paramName}' passed into ` + `'${moduleName}.${classNameStr}` + `${funcName}()' must be of type ${expectedType}.`; + }, + 'incorrect-class': ({ + expectedClassName, + paramName, + moduleName, + className, + funcName, + isReturnValueProblem + }) => { + if (!expectedClassName || !moduleName || !funcName) { + throw new Error(`Unexpected input to 'incorrect-class' error.`); + } + const classNameStr = className ? `${className}.` : ''; + if (isReturnValueProblem) { + return `The return value from ` + `'${moduleName}.${classNameStr}${funcName}()' ` + `must be an instance of class ${expectedClassName}.`; + } + return `The parameter '${paramName}' passed into ` + `'${moduleName}.${classNameStr}${funcName}()' ` + `must be an instance of class ${expectedClassName}.`; + }, + 'missing-a-method': ({ + expectedMethod, + paramName, + moduleName, + className, + funcName + }) => { + if (!expectedMethod || !paramName || !moduleName || !className || !funcName) { + throw new Error(`Unexpected input to 'missing-a-method' error.`); + } + return `${moduleName}.${className}.${funcName}() expected the ` + `'${paramName}' parameter to expose a '${expectedMethod}' method.`; + }, + 'add-to-cache-list-unexpected-type': ({ + entry + }) => { + return `An unexpected entry was passed to ` + `'workbox-precaching.PrecacheController.addToCacheList()' The entry ` + `'${JSON.stringify(entry)}' isn't supported. You must supply an array of ` + `strings with one or more characters, objects with a url property or ` + `Request objects.`; + }, + 'add-to-cache-list-conflicting-entries': ({ + firstEntry, + secondEntry + }) => { + if (!firstEntry || !secondEntry) { + throw new Error(`Unexpected input to ` + `'add-to-cache-list-duplicate-entries' error.`); + } + return `Two of the entries passed to ` + `'workbox-precaching.PrecacheController.addToCacheList()' had the URL ` + `${firstEntry} but different revision details. Workbox is ` + `unable to cache and version the asset correctly. Please remove one ` + `of the entries.`; + }, + 'plugin-error-request-will-fetch': ({ + thrownErrorMessage + }) => { + if (!thrownErrorMessage) { + throw new Error(`Unexpected input to ` + `'plugin-error-request-will-fetch', error.`); + } + return `An error was thrown by a plugins 'requestWillFetch()' method. ` + `The thrown error message was: '${thrownErrorMessage}'.`; + }, + 'invalid-cache-name': ({ + cacheNameId, + value + }) => { + if (!cacheNameId) { + throw new Error(`Expected a 'cacheNameId' for error 'invalid-cache-name'`); + } + return `You must provide a name containing at least one character for ` + `setCacheDetails({${cacheNameId}: '...'}). Received a value of ` + `'${JSON.stringify(value)}'`; + }, + 'unregister-route-but-not-found-with-method': ({ + method + }) => { + if (!method) { + throw new Error(`Unexpected input to ` + `'unregister-route-but-not-found-with-method' error.`); + } + return `The route you're trying to unregister was not previously ` + `registered for the method type '${method}'.`; + }, + 'unregister-route-route-not-registered': () => { + return `The route you're trying to unregister was not previously ` + `registered.`; + }, + 'queue-replay-failed': ({ + name + }) => { + return `Replaying the background sync queue '${name}' failed.`; + }, + 'duplicate-queue-name': ({ + name + }) => { + return `The Queue name '${name}' is already being used. ` + `All instances of backgroundSync.Queue must be given unique names.`; + }, + 'expired-test-without-max-age': ({ + methodName, + paramName + }) => { + return `The '${methodName}()' method can only be used when the ` + `'${paramName}' is used in the constructor.`; + }, + 'unsupported-route-type': ({ + moduleName, + className, + funcName, + paramName + }) => { + return `The supplied '${paramName}' parameter was an unsupported type. ` + `Please check the docs for ${moduleName}.${className}.${funcName} for ` + `valid input types.`; + }, + 'not-array-of-class': ({ + value, + expectedClass, + moduleName, + className, + funcName, + paramName + }) => { + return `The supplied '${paramName}' parameter must be an array of ` + `'${expectedClass}' objects. Received '${JSON.stringify(value)},'. ` + `Please check the call to ${moduleName}.${className}.${funcName}() ` + `to fix the issue.`; + }, + 'max-entries-or-age-required': ({ + moduleName, + className, + funcName + }) => { + return `You must define either config.maxEntries or config.maxAgeSeconds` + `in ${moduleName}.${className}.${funcName}`; + }, + 'statuses-or-headers-required': ({ + moduleName, + className, + funcName + }) => { + return `You must define either config.statuses or config.headers` + `in ${moduleName}.${className}.${funcName}`; + }, + 'invalid-string': ({ + moduleName, + funcName, + paramName + }) => { + if (!paramName || !moduleName || !funcName) { + throw new Error(`Unexpected input to 'invalid-string' error.`); + } + return `When using strings, the '${paramName}' parameter must start with ` + `'http' (for cross-origin matches) or '/' (for same-origin matches). ` + `Please see the docs for ${moduleName}.${funcName}() for ` + `more info.`; + }, + 'channel-name-required': () => { + return `You must provide a channelName to construct a ` + `BroadcastCacheUpdate instance.`; + }, + 'invalid-responses-are-same-args': () => { + return `The arguments passed into responsesAreSame() appear to be ` + `invalid. Please ensure valid Responses are used.`; + }, + 'expire-custom-caches-only': () => { + return `You must provide a 'cacheName' property when using the ` + `expiration plugin with a runtime caching strategy.`; + }, + 'unit-must-be-bytes': ({ + normalizedRangeHeader + }) => { + if (!normalizedRangeHeader) { + throw new Error(`Unexpected input to 'unit-must-be-bytes' error.`); + } + return `The 'unit' portion of the Range header must be set to 'bytes'. ` + `The Range header provided was "${normalizedRangeHeader}"`; + }, + 'single-range-only': ({ + normalizedRangeHeader + }) => { + if (!normalizedRangeHeader) { + throw new Error(`Unexpected input to 'single-range-only' error.`); + } + return `Multiple ranges are not supported. Please use a single start ` + `value, and optional end value. The Range header provided was ` + `"${normalizedRangeHeader}"`; + }, + 'invalid-range-values': ({ + normalizedRangeHeader + }) => { + if (!normalizedRangeHeader) { + throw new Error(`Unexpected input to 'invalid-range-values' error.`); + } + return `The Range header is missing both start and end values. At least ` + `one of those values is needed. The Range header provided was ` + `"${normalizedRangeHeader}"`; + }, + 'no-range-header': () => { + return `No Range header was found in the Request provided.`; + }, + 'range-not-satisfiable': ({ + size, + start, + end + }) => { + return `The start (${start}) and end (${end}) values in the Range are ` + `not satisfiable by the cached response, which is ${size} bytes.`; + }, + 'attempt-to-cache-non-get-request': ({ + url, + method + }) => { + return `Unable to cache '${url}' because it is a '${method}' request and ` + `only 'GET' requests can be cached.`; + }, + 'cache-put-with-no-response': ({ + url + }) => { + return `There was an attempt to cache '${url}' but the response was not ` + `defined.`; + }, + 'no-response': ({ + url, + error + }) => { + let message = `The strategy could not generate a response for '${url}'.`; + if (error) { + message += ` The underlying error is ${error}.`; + } + return message; + }, + 'bad-precaching-response': ({ + url, + status + }) => { + return `The precaching request for '${url}' failed` + (status ? ` with an HTTP status of ${status}.` : `.`); + }, + 'non-precached-url': ({ + url + }) => { + return `createHandlerBoundToURL('${url}') was called, but that URL is ` + `not precached. Please pass in a URL that is precached instead.`; + }, + 'add-to-cache-list-conflicting-integrities': ({ + url + }) => { + return `Two of the entries passed to ` + `'workbox-precaching.PrecacheController.addToCacheList()' had the URL ` + `${url} with different integrity values. Please remove one of them.`; + }, + 'missing-precache-entry': ({ + cacheName, + url + }) => { + return `Unable to find a precached response in ${cacheName} for ${url}.`; + }, + 'cross-origin-copy-response': ({ + origin + }) => { + return `workbox-core.copyResponse() can only be used with same-origin ` + `responses. It was passed a response with origin ${origin}.`; + }, + 'opaque-streams-source': ({ + type + }) => { + const message = `One of the workbox-streams sources resulted in an ` + `'${type}' response.`; + if (type === 'opaqueredirect') { + return `${message} Please do not use a navigation request that results ` + `in a redirect as a source.`; + } + return `${message} Please ensure your sources are CORS-enabled.`; + } + }; + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + const generatorFunction = (code, details = {}) => { + const message = messages[code]; + if (!message) { + throw new Error(`Unable to find message for code '${code}'.`); + } + return message(details); + }; + const messageGenerator = generatorFunction; + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * Workbox errors should be thrown with this class. + * This allows use to ensure the type easily in tests, + * helps developers identify errors from workbox + * easily and allows use to optimise error + * messages correctly. + * + * @private + */ + class WorkboxError extends Error { + /** + * + * @param {string} errorCode The error code that + * identifies this particular error. + * @param {Object=} details Any relevant arguments + * that will help developers identify issues should + * be added as a key on the context object. + */ + constructor(errorCode, details) { + const message = messageGenerator(errorCode, details); + super(message); + this.name = errorCode; + this.details = details; + } + } + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /* + * This method throws if the supplied value is not an array. + * The destructed values are required to produce a meaningful error for users. + * The destructed and restructured object is so it's clear what is + * needed. + */ + const isArray = (value, details) => { + if (!Array.isArray(value)) { + throw new WorkboxError('not-an-array', details); + } + }; + const hasMethod = (object, expectedMethod, details) => { + const type = typeof object[expectedMethod]; + if (type !== 'function') { + details['expectedMethod'] = expectedMethod; + throw new WorkboxError('missing-a-method', details); + } + }; + const isType = (object, expectedType, details) => { + if (typeof object !== expectedType) { + details['expectedType'] = expectedType; + throw new WorkboxError('incorrect-type', details); + } + }; + const isInstance = (object, + // Need the general type to do the check later. + // eslint-disable-next-line @typescript-eslint/ban-types + expectedClass, details) => { + if (!(object instanceof expectedClass)) { + details['expectedClassName'] = expectedClass.name; + throw new WorkboxError('incorrect-class', details); + } + }; + const isOneOf = (value, validValues, details) => { + if (!validValues.includes(value)) { + details['validValueDescription'] = `Valid values are ${JSON.stringify(validValues)}.`; + throw new WorkboxError('invalid-value', details); + } + }; + const isArrayOfClass = (value, + // Need general type to do check later. + expectedClass, + // eslint-disable-line + details) => { + const error = new WorkboxError('not-array-of-class', details); + if (!Array.isArray(value)) { + throw error; + } + for (const item of value) { + if (!(item instanceof expectedClass)) { + throw error; + } + } + }; + const finalAssertExports = { + hasMethod, + isArray, + isInstance, + isOneOf, + isType, + isArrayOfClass + }; + + // @ts-ignore + try { + self['workbox:routing:7.3.0'] && _(); + } catch (e) {} + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * The default HTTP method, 'GET', used when there's no specific method + * configured for a route. + * + * @type {string} + * + * @private + */ + const defaultMethod = 'GET'; + /** + * The list of valid HTTP methods associated with requests that could be routed. + * + * @type {Array} + * + * @private + */ + const validMethods = ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT']; + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * @param {function()|Object} handler Either a function, or an object with a + * 'handle' method. + * @return {Object} An object with a handle method. + * + * @private + */ + const normalizeHandler = handler => { + if (handler && typeof handler === 'object') { + { + finalAssertExports.hasMethod(handler, 'handle', { + moduleName: 'workbox-routing', + className: 'Route', + funcName: 'constructor', + paramName: 'handler' + }); + } + return handler; + } else { + { + finalAssertExports.isType(handler, 'function', { + moduleName: 'workbox-routing', + className: 'Route', + funcName: 'constructor', + paramName: 'handler' + }); + } + return { + handle: handler + }; + } + }; + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * A `Route` consists of a pair of callback functions, "match" and "handler". + * The "match" callback determine if a route should be used to "handle" a + * request by returning a non-falsy value if it can. The "handler" callback + * is called when there is a match and should return a Promise that resolves + * to a `Response`. + * + * @memberof workbox-routing + */ + class Route { + /** + * Constructor for Route class. + * + * @param {workbox-routing~matchCallback} match + * A callback function that determines whether the route matches a given + * `fetch` event by returning a non-falsy value. + * @param {workbox-routing~handlerCallback} handler A callback + * function that returns a Promise resolving to a Response. + * @param {string} [method='GET'] The HTTP method to match the Route + * against. + */ + constructor(match, handler, method = defaultMethod) { + { + finalAssertExports.isType(match, 'function', { + moduleName: 'workbox-routing', + className: 'Route', + funcName: 'constructor', + paramName: 'match' + }); + if (method) { + finalAssertExports.isOneOf(method, validMethods, { + paramName: 'method' + }); + } + } + // These values are referenced directly by Router so cannot be + // altered by minificaton. + this.handler = normalizeHandler(handler); + this.match = match; + this.method = method; + } + /** + * + * @param {workbox-routing-handlerCallback} handler A callback + * function that returns a Promise resolving to a Response + */ + setCatchHandler(handler) { + this.catchHandler = normalizeHandler(handler); + } + } + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * RegExpRoute makes it easy to create a regular expression based + * {@link workbox-routing.Route}. + * + * For same-origin requests the RegExp only needs to match part of the URL. For + * requests against third-party servers, you must define a RegExp that matches + * the start of the URL. + * + * @memberof workbox-routing + * @extends workbox-routing.Route + */ + class RegExpRoute extends Route { + /** + * If the regular expression contains + * [capture groups]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references}, + * the captured values will be passed to the + * {@link workbox-routing~handlerCallback} `params` + * argument. + * + * @param {RegExp} regExp The regular expression to match against URLs. + * @param {workbox-routing~handlerCallback} handler A callback + * function that returns a Promise resulting in a Response. + * @param {string} [method='GET'] The HTTP method to match the Route + * against. + */ + constructor(regExp, handler, method) { + { + finalAssertExports.isInstance(regExp, RegExp, { + moduleName: 'workbox-routing', + className: 'RegExpRoute', + funcName: 'constructor', + paramName: 'pattern' + }); + } + const match = ({ + url + }) => { + const result = regExp.exec(url.href); + // Return immediately if there's no match. + if (!result) { + return; + } + // Require that the match start at the first character in the URL string + // if it's a cross-origin request. + // See https://github.com/GoogleChrome/workbox/issues/281 for the context + // behind this behavior. + if (url.origin !== location.origin && result.index !== 0) { + { + logger.debug(`The regular expression '${regExp.toString()}' only partially matched ` + `against the cross-origin URL '${url.toString()}'. RegExpRoute's will only ` + `handle cross-origin requests if they match the entire URL.`); + } + return; + } + // If the route matches, but there aren't any capture groups defined, then + // this will return [], which is truthy and therefore sufficient to + // indicate a match. + // If there are capture groups, then it will return their values. + return result.slice(1); + }; + super(match, handler, method); + } + } + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + const getFriendlyURL = url => { + const urlObj = new URL(String(url), location.href); + // See https://github.com/GoogleChrome/workbox/issues/2323 + // We want to include everything, except for the origin if it's same-origin. + return urlObj.href.replace(new RegExp(`^${location.origin}`), ''); + }; + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * The Router can be used to process a `FetchEvent` using one or more + * {@link workbox-routing.Route}, responding with a `Response` if + * a matching route exists. + * + * If no route matches a given a request, the Router will use a "default" + * handler if one is defined. + * + * Should the matching Route throw an error, the Router will use a "catch" + * handler if one is defined to gracefully deal with issues and respond with a + * Request. + * + * If a request matches multiple routes, the **earliest** registered route will + * be used to respond to the request. + * + * @memberof workbox-routing + */ + class Router { + /** + * Initializes a new Router. + */ + constructor() { + this._routes = new Map(); + this._defaultHandlerMap = new Map(); + } + /** + * @return {Map>} routes A `Map` of HTTP + * method name ('GET', etc.) to an array of all the corresponding `Route` + * instances that are registered. + */ + get routes() { + return this._routes; + } + /** + * Adds a fetch event listener to respond to events when a route matches + * the event's request. + */ + addFetchListener() { + // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705 + self.addEventListener('fetch', event => { + const { + request + } = event; + const responsePromise = this.handleRequest({ + request, + event + }); + if (responsePromise) { + event.respondWith(responsePromise); + } + }); + } + /** + * Adds a message event listener for URLs to cache from the window. + * This is useful to cache resources loaded on the page prior to when the + * service worker started controlling it. + * + * The format of the message data sent from the window should be as follows. + * Where the `urlsToCache` array may consist of URL strings or an array of + * URL string + `requestInit` object (the same as you'd pass to `fetch()`). + * + * ``` + * { + * type: 'CACHE_URLS', + * payload: { + * urlsToCache: [ + * './script1.js', + * './script2.js', + * ['./script3.js', {mode: 'no-cors'}], + * ], + * }, + * } + * ``` + */ + addCacheListener() { + // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705 + self.addEventListener('message', event => { + // event.data is type 'any' + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + if (event.data && event.data.type === 'CACHE_URLS') { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const { + payload + } = event.data; + { + logger.debug(`Caching URLs from the window`, payload.urlsToCache); + } + const requestPromises = Promise.all(payload.urlsToCache.map(entry => { + if (typeof entry === 'string') { + entry = [entry]; + } + const request = new Request(...entry); + return this.handleRequest({ + request, + event + }); + // TODO(philipwalton): TypeScript errors without this typecast for + // some reason (probably a bug). The real type here should work but + // doesn't: `Array | undefined>`. + })); // TypeScript + event.waitUntil(requestPromises); + // If a MessageChannel was used, reply to the message on success. + if (event.ports && event.ports[0]) { + void requestPromises.then(() => event.ports[0].postMessage(true)); + } + } + }); + } + /** + * Apply the routing rules to a FetchEvent object to get a Response from an + * appropriate Route's handler. + * + * @param {Object} options + * @param {Request} options.request The request to handle. + * @param {ExtendableEvent} options.event The event that triggered the + * request. + * @return {Promise|undefined} A promise is returned if a + * registered route can handle the request. If there is no matching + * route and there's no `defaultHandler`, `undefined` is returned. + */ + handleRequest({ + request, + event + }) { + { + finalAssertExports.isInstance(request, Request, { + moduleName: 'workbox-routing', + className: 'Router', + funcName: 'handleRequest', + paramName: 'options.request' + }); + } + const url = new URL(request.url, location.href); + if (!url.protocol.startsWith('http')) { + { + logger.debug(`Workbox Router only supports URLs that start with 'http'.`); + } + return; + } + const sameOrigin = url.origin === location.origin; + const { + params, + route + } = this.findMatchingRoute({ + event, + request, + sameOrigin, + url + }); + let handler = route && route.handler; + const debugMessages = []; + { + if (handler) { + debugMessages.push([`Found a route to handle this request:`, route]); + if (params) { + debugMessages.push([`Passing the following params to the route's handler:`, params]); + } + } + } + // If we don't have a handler because there was no matching route, then + // fall back to defaultHandler if that's defined. + const method = request.method; + if (!handler && this._defaultHandlerMap.has(method)) { + { + debugMessages.push(`Failed to find a matching route. Falling ` + `back to the default handler for ${method}.`); + } + handler = this._defaultHandlerMap.get(method); + } + if (!handler) { + { + // No handler so Workbox will do nothing. If logs is set of debug + // i.e. verbose, we should print out this information. + logger.debug(`No route found for: ${getFriendlyURL(url)}`); + } + return; + } + { + // We have a handler, meaning Workbox is going to handle the route. + // print the routing details to the console. + logger.groupCollapsed(`Router is responding to: ${getFriendlyURL(url)}`); + debugMessages.forEach(msg => { + if (Array.isArray(msg)) { + logger.log(...msg); + } else { + logger.log(msg); + } + }); + logger.groupEnd(); + } + // Wrap in try and catch in case the handle method throws a synchronous + // error. It should still callback to the catch handler. + let responsePromise; + try { + responsePromise = handler.handle({ + url, + request, + event, + params + }); + } catch (err) { + responsePromise = Promise.reject(err); + } + // Get route's catch handler, if it exists + const catchHandler = route && route.catchHandler; + if (responsePromise instanceof Promise && (this._catchHandler || catchHandler)) { + responsePromise = responsePromise.catch(async err => { + // If there's a route catch handler, process that first + if (catchHandler) { + { + // Still include URL here as it will be async from the console group + // and may not make sense without the URL + logger.groupCollapsed(`Error thrown when responding to: ` + ` ${getFriendlyURL(url)}. Falling back to route's Catch Handler.`); + logger.error(`Error thrown by:`, route); + logger.error(err); + logger.groupEnd(); + } + try { + return await catchHandler.handle({ + url, + request, + event, + params + }); + } catch (catchErr) { + if (catchErr instanceof Error) { + err = catchErr; + } + } + } + if (this._catchHandler) { + { + // Still include URL here as it will be async from the console group + // and may not make sense without the URL + logger.groupCollapsed(`Error thrown when responding to: ` + ` ${getFriendlyURL(url)}. Falling back to global Catch Handler.`); + logger.error(`Error thrown by:`, route); + logger.error(err); + logger.groupEnd(); + } + return this._catchHandler.handle({ + url, + request, + event + }); + } + throw err; + }); + } + return responsePromise; + } + /** + * Checks a request and URL (and optionally an event) against the list of + * registered routes, and if there's a match, returns the corresponding + * route along with any params generated by the match. + * + * @param {Object} options + * @param {URL} options.url + * @param {boolean} options.sameOrigin The result of comparing `url.origin` + * against the current origin. + * @param {Request} options.request The request to match. + * @param {Event} options.event The corresponding event. + * @return {Object} An object with `route` and `params` properties. + * They are populated if a matching route was found or `undefined` + * otherwise. + */ + findMatchingRoute({ + url, + sameOrigin, + request, + event + }) { + const routes = this._routes.get(request.method) || []; + for (const route of routes) { + let params; + // route.match returns type any, not possible to change right now. + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const matchResult = route.match({ + url, + sameOrigin, + request, + event + }); + if (matchResult) { + { + // Warn developers that using an async matchCallback is almost always + // not the right thing to do. + if (matchResult instanceof Promise) { + logger.warn(`While routing ${getFriendlyURL(url)}, an async ` + `matchCallback function was used. Please convert the ` + `following route to use a synchronous matchCallback function:`, route); + } + } + // See https://github.com/GoogleChrome/workbox/issues/2079 + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + params = matchResult; + if (Array.isArray(params) && params.length === 0) { + // Instead of passing an empty array in as params, use undefined. + params = undefined; + } else if (matchResult.constructor === Object && + // eslint-disable-line + Object.keys(matchResult).length === 0) { + // Instead of passing an empty object in as params, use undefined. + params = undefined; + } else if (typeof matchResult === 'boolean') { + // For the boolean value true (rather than just something truth-y), + // don't set params. + // See https://github.com/GoogleChrome/workbox/pull/2134#issuecomment-513924353 + params = undefined; + } + // Return early if have a match. + return { + route, + params + }; + } + } + // If no match was found above, return and empty object. + return {}; + } + /** + * Define a default `handler` that's called when no routes explicitly + * match the incoming request. + * + * Each HTTP method ('GET', 'POST', etc.) gets its own default handler. + * + * Without a default handler, unmatched requests will go against the + * network as if there were no service worker present. + * + * @param {workbox-routing~handlerCallback} handler A callback + * function that returns a Promise resulting in a Response. + * @param {string} [method='GET'] The HTTP method to associate with this + * default handler. Each method has its own default. + */ + setDefaultHandler(handler, method = defaultMethod) { + this._defaultHandlerMap.set(method, normalizeHandler(handler)); + } + /** + * If a Route throws an error while handling a request, this `handler` + * will be called and given a chance to provide a response. + * + * @param {workbox-routing~handlerCallback} handler A callback + * function that returns a Promise resulting in a Response. + */ + setCatchHandler(handler) { + this._catchHandler = normalizeHandler(handler); + } + /** + * Registers a route with the router. + * + * @param {workbox-routing.Route} route The route to register. + */ + registerRoute(route) { + { + finalAssertExports.isType(route, 'object', { + moduleName: 'workbox-routing', + className: 'Router', + funcName: 'registerRoute', + paramName: 'route' + }); + finalAssertExports.hasMethod(route, 'match', { + moduleName: 'workbox-routing', + className: 'Router', + funcName: 'registerRoute', + paramName: 'route' + }); + finalAssertExports.isType(route.handler, 'object', { + moduleName: 'workbox-routing', + className: 'Router', + funcName: 'registerRoute', + paramName: 'route' + }); + finalAssertExports.hasMethod(route.handler, 'handle', { + moduleName: 'workbox-routing', + className: 'Router', + funcName: 'registerRoute', + paramName: 'route.handler' + }); + finalAssertExports.isType(route.method, 'string', { + moduleName: 'workbox-routing', + className: 'Router', + funcName: 'registerRoute', + paramName: 'route.method' + }); + } + if (!this._routes.has(route.method)) { + this._routes.set(route.method, []); + } + // Give precedence to all of the earlier routes by adding this additional + // route to the end of the array. + this._routes.get(route.method).push(route); + } + /** + * Unregisters a route with the router. + * + * @param {workbox-routing.Route} route The route to unregister. + */ + unregisterRoute(route) { + if (!this._routes.has(route.method)) { + throw new WorkboxError('unregister-route-but-not-found-with-method', { + method: route.method + }); + } + const routeIndex = this._routes.get(route.method).indexOf(route); + if (routeIndex > -1) { + this._routes.get(route.method).splice(routeIndex, 1); + } else { + throw new WorkboxError('unregister-route-route-not-registered'); + } + } + } + + /* + Copyright 2019 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + let defaultRouter; + /** + * Creates a new, singleton Router instance if one does not exist. If one + * does already exist, that instance is returned. + * + * @private + * @return {Router} + */ + const getOrCreateDefaultRouter = () => { + if (!defaultRouter) { + defaultRouter = new Router(); + // The helpers that use the default Router assume these listeners exist. + defaultRouter.addFetchListener(); + defaultRouter.addCacheListener(); + } + return defaultRouter; + }; + + /* + Copyright 2019 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * Easily register a RegExp, string, or function with a caching + * strategy to a singleton Router instance. + * + * This method will generate a Route for you if needed and + * call {@link workbox-routing.Router#registerRoute}. + * + * @param {RegExp|string|workbox-routing.Route~matchCallback|workbox-routing.Route} capture + * If the capture param is a `Route`, all other arguments will be ignored. + * @param {workbox-routing~handlerCallback} [handler] A callback + * function that returns a Promise resulting in a Response. This parameter + * is required if `capture` is not a `Route` object. + * @param {string} [method='GET'] The HTTP method to match the Route + * against. + * @return {workbox-routing.Route} The generated `Route`. + * + * @memberof workbox-routing + */ + function registerRoute(capture, handler, method) { + let route; + if (typeof capture === 'string') { + const captureUrl = new URL(capture, location.href); + { + if (!(capture.startsWith('/') || capture.startsWith('http'))) { + throw new WorkboxError('invalid-string', { + moduleName: 'workbox-routing', + funcName: 'registerRoute', + paramName: 'capture' + }); + } + // We want to check if Express-style wildcards are in the pathname only. + // TODO: Remove this log message in v4. + const valueToCheck = capture.startsWith('http') ? captureUrl.pathname : capture; + // See https://github.com/pillarjs/path-to-regexp#parameters + const wildcards = '[*:?+]'; + if (new RegExp(`${wildcards}`).exec(valueToCheck)) { + logger.debug(`The '$capture' parameter contains an Express-style wildcard ` + `character (${wildcards}). Strings are now always interpreted as ` + `exact matches; use a RegExp for partial or wildcard matches.`); + } + } + const matchCallback = ({ + url + }) => { + { + if (url.pathname === captureUrl.pathname && url.origin !== captureUrl.origin) { + logger.debug(`${capture} only partially matches the cross-origin URL ` + `${url.toString()}. This route will only handle cross-origin requests ` + `if they match the entire URL.`); + } + } + return url.href === captureUrl.href; + }; + // If `capture` is a string then `handler` and `method` must be present. + route = new Route(matchCallback, handler, method); + } else if (capture instanceof RegExp) { + // If `capture` is a `RegExp` then `handler` and `method` must be present. + route = new RegExpRoute(capture, handler, method); + } else if (typeof capture === 'function') { + // If `capture` is a function then `handler` and `method` must be present. + route = new Route(capture, handler, method); + } else if (capture instanceof Route) { + route = capture; + } else { + throw new WorkboxError('unsupported-route-type', { + moduleName: 'workbox-routing', + funcName: 'registerRoute', + paramName: 'capture' + }); + } + const defaultRouter = getOrCreateDefaultRouter(); + defaultRouter.registerRoute(route); + return route; + } + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + const _cacheNameDetails = { + googleAnalytics: 'googleAnalytics', + precache: 'precache-v2', + prefix: 'workbox', + runtime: 'runtime', + suffix: typeof registration !== 'undefined' ? registration.scope : '' + }; + const _createCacheName = cacheName => { + return [_cacheNameDetails.prefix, cacheName, _cacheNameDetails.suffix].filter(value => value && value.length > 0).join('-'); + }; + const eachCacheNameDetail = fn => { + for (const key of Object.keys(_cacheNameDetails)) { + fn(key); + } + }; + const cacheNames = { + updateDetails: details => { + eachCacheNameDetail(key => { + if (typeof details[key] === 'string') { + _cacheNameDetails[key] = details[key]; + } + }); + }, + getGoogleAnalyticsName: userCacheName => { + return userCacheName || _createCacheName(_cacheNameDetails.googleAnalytics); + }, + getPrecacheName: userCacheName => { + return userCacheName || _createCacheName(_cacheNameDetails.precache); + }, + getPrefix: () => { + return _cacheNameDetails.prefix; + }, + getRuntimeName: userCacheName => { + return userCacheName || _createCacheName(_cacheNameDetails.runtime); + }, + getSuffix: () => { + return _cacheNameDetails.suffix; + } + }; + + /* + Copyright 2020 Google LLC + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * A utility method that makes it easier to use `event.waitUntil` with + * async functions and return the result. + * + * @param {ExtendableEvent} event + * @param {Function} asyncFn + * @return {Function} + * @private + */ + function waitUntil(event, asyncFn) { + const returnPromise = asyncFn(); + event.waitUntil(returnPromise); + return returnPromise; + } + + // @ts-ignore + try { + self['workbox:precaching:7.3.0'] && _(); + } catch (e) {} + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + // Name of the search parameter used to store revision info. + const REVISION_SEARCH_PARAM = '__WB_REVISION__'; + /** + * Converts a manifest entry into a versioned URL suitable for precaching. + * + * @param {Object|string} entry + * @return {string} A URL with versioning info. + * + * @private + * @memberof workbox-precaching + */ + function createCacheKey(entry) { + if (!entry) { + throw new WorkboxError('add-to-cache-list-unexpected-type', { + entry + }); + } + // If a precache manifest entry is a string, it's assumed to be a versioned + // URL, like '/app.abcd1234.js'. Return as-is. + if (typeof entry === 'string') { + const urlObject = new URL(entry, location.href); + return { + cacheKey: urlObject.href, + url: urlObject.href + }; + } + const { + revision, + url + } = entry; + if (!url) { + throw new WorkboxError('add-to-cache-list-unexpected-type', { + entry + }); + } + // If there's just a URL and no revision, then it's also assumed to be a + // versioned URL. + if (!revision) { + const urlObject = new URL(url, location.href); + return { + cacheKey: urlObject.href, + url: urlObject.href + }; + } + // Otherwise, construct a properly versioned URL using the custom Workbox + // search parameter along with the revision info. + const cacheKeyURL = new URL(url, location.href); + const originalURL = new URL(url, location.href); + cacheKeyURL.searchParams.set(REVISION_SEARCH_PARAM, revision); + return { + cacheKey: cacheKeyURL.href, + url: originalURL.href + }; + } + + /* + Copyright 2020 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * A plugin, designed to be used with PrecacheController, to determine the + * of assets that were updated (or not updated) during the install event. + * + * @private + */ + class PrecacheInstallReportPlugin { + constructor() { + this.updatedURLs = []; + this.notUpdatedURLs = []; + this.handlerWillStart = async ({ + request, + state + }) => { + // TODO: `state` should never be undefined... + if (state) { + state.originalRequest = request; + } + }; + this.cachedResponseWillBeUsed = async ({ + event, + state, + cachedResponse + }) => { + if (event.type === 'install') { + if (state && state.originalRequest && state.originalRequest instanceof Request) { + // TODO: `state` should never be undefined... + const url = state.originalRequest.url; + if (cachedResponse) { + this.notUpdatedURLs.push(url); + } else { + this.updatedURLs.push(url); + } + } + } + return cachedResponse; + }; + } + } + + /* + Copyright 2020 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * A plugin, designed to be used with PrecacheController, to translate URLs into + * the corresponding cache key, based on the current revision info. + * + * @private + */ + class PrecacheCacheKeyPlugin { + constructor({ + precacheController + }) { + this.cacheKeyWillBeUsed = async ({ + request, + params + }) => { + // Params is type any, can't change right now. + /* eslint-disable */ + const cacheKey = (params === null || params === void 0 ? void 0 : params.cacheKey) || this._precacheController.getCacheKeyForURL(request.url); + /* eslint-enable */ + return cacheKey ? new Request(cacheKey, { + headers: request.headers + }) : request; + }; + this._precacheController = precacheController; + } + } + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * @param {string} groupTitle + * @param {Array} deletedURLs + * + * @private + */ + const logGroup = (groupTitle, deletedURLs) => { + logger.groupCollapsed(groupTitle); + for (const url of deletedURLs) { + logger.log(url); + } + logger.groupEnd(); + }; + /** + * @param {Array} deletedURLs + * + * @private + * @memberof workbox-precaching + */ + function printCleanupDetails(deletedURLs) { + const deletionCount = deletedURLs.length; + if (deletionCount > 0) { + logger.groupCollapsed(`During precaching cleanup, ` + `${deletionCount} cached ` + `request${deletionCount === 1 ? ' was' : 's were'} deleted.`); + logGroup('Deleted Cache Requests', deletedURLs); + logger.groupEnd(); + } + } + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * @param {string} groupTitle + * @param {Array} urls + * + * @private + */ + function _nestedGroup(groupTitle, urls) { + if (urls.length === 0) { + return; + } + logger.groupCollapsed(groupTitle); + for (const url of urls) { + logger.log(url); + } + logger.groupEnd(); + } + /** + * @param {Array} urlsToPrecache + * @param {Array} urlsAlreadyPrecached + * + * @private + * @memberof workbox-precaching + */ + function printInstallDetails(urlsToPrecache, urlsAlreadyPrecached) { + const precachedCount = urlsToPrecache.length; + const alreadyPrecachedCount = urlsAlreadyPrecached.length; + if (precachedCount || alreadyPrecachedCount) { + let message = `Precaching ${precachedCount} file${precachedCount === 1 ? '' : 's'}.`; + if (alreadyPrecachedCount > 0) { + message += ` ${alreadyPrecachedCount} ` + `file${alreadyPrecachedCount === 1 ? ' is' : 's are'} already cached.`; + } + logger.groupCollapsed(message); + _nestedGroup(`View newly precached URLs.`, urlsToPrecache); + _nestedGroup(`View previously precached URLs.`, urlsAlreadyPrecached); + logger.groupEnd(); + } + } + + /* + Copyright 2019 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + let supportStatus; + /** + * A utility function that determines whether the current browser supports + * constructing a new `Response` from a `response.body` stream. + * + * @return {boolean} `true`, if the current browser can successfully + * construct a `Response` from a `response.body` stream, `false` otherwise. + * + * @private + */ + function canConstructResponseFromBodyStream() { + if (supportStatus === undefined) { + const testResponse = new Response(''); + if ('body' in testResponse) { + try { + new Response(testResponse.body); + supportStatus = true; + } catch (error) { + supportStatus = false; + } + } + supportStatus = false; + } + return supportStatus; + } + + /* + Copyright 2019 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * Allows developers to copy a response and modify its `headers`, `status`, + * or `statusText` values (the values settable via a + * [`ResponseInit`]{@link https://developer.mozilla.org/en-US/docs/Web/API/Response/Response#Syntax} + * object in the constructor). + * To modify these values, pass a function as the second argument. That + * function will be invoked with a single object with the response properties + * `{headers, status, statusText}`. The return value of this function will + * be used as the `ResponseInit` for the new `Response`. To change the values + * either modify the passed parameter(s) and return it, or return a totally + * new object. + * + * This method is intentionally limited to same-origin responses, regardless of + * whether CORS was used or not. + * + * @param {Response} response + * @param {Function} modifier + * @memberof workbox-core + */ + async function copyResponse(response, modifier) { + let origin = null; + // If response.url isn't set, assume it's cross-origin and keep origin null. + if (response.url) { + const responseURL = new URL(response.url); + origin = responseURL.origin; + } + if (origin !== self.location.origin) { + throw new WorkboxError('cross-origin-copy-response', { + origin + }); + } + const clonedResponse = response.clone(); + // Create a fresh `ResponseInit` object by cloning the headers. + const responseInit = { + headers: new Headers(clonedResponse.headers), + status: clonedResponse.status, + statusText: clonedResponse.statusText + }; + // Apply any user modifications. + const modifiedResponseInit = modifier ? modifier(responseInit) : responseInit; + // Create the new response from the body stream and `ResponseInit` + // modifications. Note: not all browsers support the Response.body stream, + // so fall back to reading the entire body into memory as a blob. + const body = canConstructResponseFromBodyStream() ? clonedResponse.body : await clonedResponse.blob(); + return new Response(body, modifiedResponseInit); + } + + /* + Copyright 2020 Google LLC + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + function stripParams(fullURL, ignoreParams) { + const strippedURL = new URL(fullURL); + for (const param of ignoreParams) { + strippedURL.searchParams.delete(param); + } + return strippedURL.href; + } + /** + * Matches an item in the cache, ignoring specific URL params. This is similar + * to the `ignoreSearch` option, but it allows you to ignore just specific + * params (while continuing to match on the others). + * + * @private + * @param {Cache} cache + * @param {Request} request + * @param {Object} matchOptions + * @param {Array} ignoreParams + * @return {Promise} + */ + async function cacheMatchIgnoreParams(cache, request, ignoreParams, matchOptions) { + const strippedRequestURL = stripParams(request.url, ignoreParams); + // If the request doesn't include any ignored params, match as normal. + if (request.url === strippedRequestURL) { + return cache.match(request, matchOptions); + } + // Otherwise, match by comparing keys + const keysOptions = Object.assign(Object.assign({}, matchOptions), { + ignoreSearch: true + }); + const cacheKeys = await cache.keys(request, keysOptions); + for (const cacheKey of cacheKeys) { + const strippedCacheKeyURL = stripParams(cacheKey.url, ignoreParams); + if (strippedRequestURL === strippedCacheKeyURL) { + return cache.match(cacheKey, matchOptions); + } + } + return; + } + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * The Deferred class composes Promises in a way that allows for them to be + * resolved or rejected from outside the constructor. In most cases promises + * should be used directly, but Deferreds can be necessary when the logic to + * resolve a promise must be separate. + * + * @private + */ + class Deferred { + /** + * Creates a promise and exposes its resolve and reject functions as methods. + */ + constructor() { + this.promise = new Promise((resolve, reject) => { + this.resolve = resolve; + this.reject = reject; + }); + } + } + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + // Callbacks to be executed whenever there's a quota error. + // Can't change Function type right now. + // eslint-disable-next-line @typescript-eslint/ban-types + const quotaErrorCallbacks = new Set(); + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * Runs all of the callback functions, one at a time sequentially, in the order + * in which they were registered. + * + * @memberof workbox-core + * @private + */ + async function executeQuotaErrorCallbacks() { + { + logger.log(`About to run ${quotaErrorCallbacks.size} ` + `callbacks to clean up caches.`); + } + for (const callback of quotaErrorCallbacks) { + await callback(); + { + logger.log(callback, 'is complete.'); + } + } + { + logger.log('Finished running callbacks.'); + } + } + + /* + Copyright 2019 Google LLC + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * Returns a promise that resolves and the passed number of milliseconds. + * This utility is an async/await-friendly version of `setTimeout`. + * + * @param {number} ms + * @return {Promise} + * @private + */ + function timeout(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); + } + + // @ts-ignore + try { + self['workbox:strategies:7.3.0'] && _(); + } catch (e) {} + + /* + Copyright 2020 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + function toRequest(input) { + return typeof input === 'string' ? new Request(input) : input; + } + /** + * A class created every time a Strategy instance calls + * {@link workbox-strategies.Strategy~handle} or + * {@link workbox-strategies.Strategy~handleAll} that wraps all fetch and + * cache actions around plugin callbacks and keeps track of when the strategy + * is "done" (i.e. all added `event.waitUntil()` promises have resolved). + * + * @memberof workbox-strategies + */ + class StrategyHandler { + /** + * Creates a new instance associated with the passed strategy and event + * that's handling the request. + * + * The constructor also initializes the state that will be passed to each of + * the plugins handling this request. + * + * @param {workbox-strategies.Strategy} strategy + * @param {Object} options + * @param {Request|string} options.request A request to run this strategy for. + * @param {ExtendableEvent} options.event The event associated with the + * request. + * @param {URL} [options.url] + * @param {*} [options.params] The return value from the + * {@link workbox-routing~matchCallback} (if applicable). + */ + constructor(strategy, options) { + this._cacheKeys = {}; + /** + * The request the strategy is performing (passed to the strategy's + * `handle()` or `handleAll()` method). + * @name request + * @instance + * @type {Request} + * @memberof workbox-strategies.StrategyHandler + */ + /** + * The event associated with this request. + * @name event + * @instance + * @type {ExtendableEvent} + * @memberof workbox-strategies.StrategyHandler + */ + /** + * A `URL` instance of `request.url` (if passed to the strategy's + * `handle()` or `handleAll()` method). + * Note: the `url` param will be present if the strategy was invoked + * from a workbox `Route` object. + * @name url + * @instance + * @type {URL|undefined} + * @memberof workbox-strategies.StrategyHandler + */ + /** + * A `param` value (if passed to the strategy's + * `handle()` or `handleAll()` method). + * Note: the `param` param will be present if the strategy was invoked + * from a workbox `Route` object and the + * {@link workbox-routing~matchCallback} returned + * a truthy value (it will be that value). + * @name params + * @instance + * @type {*|undefined} + * @memberof workbox-strategies.StrategyHandler + */ + { + finalAssertExports.isInstance(options.event, ExtendableEvent, { + moduleName: 'workbox-strategies', + className: 'StrategyHandler', + funcName: 'constructor', + paramName: 'options.event' + }); + } + Object.assign(this, options); + this.event = options.event; + this._strategy = strategy; + this._handlerDeferred = new Deferred(); + this._extendLifetimePromises = []; + // Copy the plugins list (since it's mutable on the strategy), + // so any mutations don't affect this handler instance. + this._plugins = [...strategy.plugins]; + this._pluginStateMap = new Map(); + for (const plugin of this._plugins) { + this._pluginStateMap.set(plugin, {}); + } + this.event.waitUntil(this._handlerDeferred.promise); + } + /** + * Fetches a given request (and invokes any applicable plugin callback + * methods) using the `fetchOptions` (for non-navigation requests) and + * `plugins` defined on the `Strategy` object. + * + * The following plugin lifecycle methods are invoked when using this method: + * - `requestWillFetch()` + * - `fetchDidSucceed()` + * - `fetchDidFail()` + * + * @param {Request|string} input The URL or request to fetch. + * @return {Promise} + */ + async fetch(input) { + const { + event + } = this; + let request = toRequest(input); + if (request.mode === 'navigate' && event instanceof FetchEvent && event.preloadResponse) { + const possiblePreloadResponse = await event.preloadResponse; + if (possiblePreloadResponse) { + { + logger.log(`Using a preloaded navigation response for ` + `'${getFriendlyURL(request.url)}'`); + } + return possiblePreloadResponse; + } + } + // If there is a fetchDidFail plugin, we need to save a clone of the + // original request before it's either modified by a requestWillFetch + // plugin or before the original request's body is consumed via fetch(). + const originalRequest = this.hasCallback('fetchDidFail') ? request.clone() : null; + try { + for (const cb of this.iterateCallbacks('requestWillFetch')) { + request = await cb({ + request: request.clone(), + event + }); + } + } catch (err) { + if (err instanceof Error) { + throw new WorkboxError('plugin-error-request-will-fetch', { + thrownErrorMessage: err.message + }); + } + } + // The request can be altered by plugins with `requestWillFetch` making + // the original request (most likely from a `fetch` event) different + // from the Request we make. Pass both to `fetchDidFail` to aid debugging. + const pluginFilteredRequest = request.clone(); + try { + let fetchResponse; + // See https://github.com/GoogleChrome/workbox/issues/1796 + fetchResponse = await fetch(request, request.mode === 'navigate' ? undefined : this._strategy.fetchOptions); + if ("development" !== 'production') { + logger.debug(`Network request for ` + `'${getFriendlyURL(request.url)}' returned a response with ` + `status '${fetchResponse.status}'.`); + } + for (const callback of this.iterateCallbacks('fetchDidSucceed')) { + fetchResponse = await callback({ + event, + request: pluginFilteredRequest, + response: fetchResponse + }); + } + return fetchResponse; + } catch (error) { + { + logger.log(`Network request for ` + `'${getFriendlyURL(request.url)}' threw an error.`, error); + } + // `originalRequest` will only exist if a `fetchDidFail` callback + // is being used (see above). + if (originalRequest) { + await this.runCallbacks('fetchDidFail', { + error: error, + event, + originalRequest: originalRequest.clone(), + request: pluginFilteredRequest.clone() + }); + } + throw error; + } + } + /** + * Calls `this.fetch()` and (in the background) runs `this.cachePut()` on + * the response generated by `this.fetch()`. + * + * The call to `this.cachePut()` automatically invokes `this.waitUntil()`, + * so you do not have to manually call `waitUntil()` on the event. + * + * @param {Request|string} input The request or URL to fetch and cache. + * @return {Promise} + */ + async fetchAndCachePut(input) { + const response = await this.fetch(input); + const responseClone = response.clone(); + void this.waitUntil(this.cachePut(input, responseClone)); + return response; + } + /** + * Matches a request from the cache (and invokes any applicable plugin + * callback methods) using the `cacheName`, `matchOptions`, and `plugins` + * defined on the strategy object. + * + * The following plugin lifecycle methods are invoked when using this method: + * - cacheKeyWillBeUsed() + * - cachedResponseWillBeUsed() + * + * @param {Request|string} key The Request or URL to use as the cache key. + * @return {Promise} A matching response, if found. + */ + async cacheMatch(key) { + const request = toRequest(key); + let cachedResponse; + const { + cacheName, + matchOptions + } = this._strategy; + const effectiveRequest = await this.getCacheKey(request, 'read'); + const multiMatchOptions = Object.assign(Object.assign({}, matchOptions), { + cacheName + }); + cachedResponse = await caches.match(effectiveRequest, multiMatchOptions); + { + if (cachedResponse) { + logger.debug(`Found a cached response in '${cacheName}'.`); + } else { + logger.debug(`No cached response found in '${cacheName}'.`); + } + } + for (const callback of this.iterateCallbacks('cachedResponseWillBeUsed')) { + cachedResponse = (await callback({ + cacheName, + matchOptions, + cachedResponse, + request: effectiveRequest, + event: this.event + })) || undefined; + } + return cachedResponse; + } + /** + * Puts a request/response pair in the cache (and invokes any applicable + * plugin callback methods) using the `cacheName` and `plugins` defined on + * the strategy object. + * + * The following plugin lifecycle methods are invoked when using this method: + * - cacheKeyWillBeUsed() + * - cacheWillUpdate() + * - cacheDidUpdate() + * + * @param {Request|string} key The request or URL to use as the cache key. + * @param {Response} response The response to cache. + * @return {Promise} `false` if a cacheWillUpdate caused the response + * not be cached, and `true` otherwise. + */ + async cachePut(key, response) { + const request = toRequest(key); + // Run in the next task to avoid blocking other cache reads. + // https://github.com/w3c/ServiceWorker/issues/1397 + await timeout(0); + const effectiveRequest = await this.getCacheKey(request, 'write'); + { + if (effectiveRequest.method && effectiveRequest.method !== 'GET') { + throw new WorkboxError('attempt-to-cache-non-get-request', { + url: getFriendlyURL(effectiveRequest.url), + method: effectiveRequest.method + }); + } + // See https://github.com/GoogleChrome/workbox/issues/2818 + const vary = response.headers.get('Vary'); + if (vary) { + logger.debug(`The response for ${getFriendlyURL(effectiveRequest.url)} ` + `has a 'Vary: ${vary}' header. ` + `Consider setting the {ignoreVary: true} option on your strategy ` + `to ensure cache matching and deletion works as expected.`); + } + } + if (!response) { + { + logger.error(`Cannot cache non-existent response for ` + `'${getFriendlyURL(effectiveRequest.url)}'.`); + } + throw new WorkboxError('cache-put-with-no-response', { + url: getFriendlyURL(effectiveRequest.url) + }); + } + const responseToCache = await this._ensureResponseSafeToCache(response); + if (!responseToCache) { + { + logger.debug(`Response '${getFriendlyURL(effectiveRequest.url)}' ` + `will not be cached.`, responseToCache); + } + return false; + } + const { + cacheName, + matchOptions + } = this._strategy; + const cache = await self.caches.open(cacheName); + const hasCacheUpdateCallback = this.hasCallback('cacheDidUpdate'); + const oldResponse = hasCacheUpdateCallback ? await cacheMatchIgnoreParams( + // TODO(philipwalton): the `__WB_REVISION__` param is a precaching + // feature. Consider into ways to only add this behavior if using + // precaching. + cache, effectiveRequest.clone(), ['__WB_REVISION__'], matchOptions) : null; + { + logger.debug(`Updating the '${cacheName}' cache with a new Response ` + `for ${getFriendlyURL(effectiveRequest.url)}.`); + } + try { + await cache.put(effectiveRequest, hasCacheUpdateCallback ? responseToCache.clone() : responseToCache); + } catch (error) { + if (error instanceof Error) { + // See https://developer.mozilla.org/en-US/docs/Web/API/DOMException#exception-QuotaExceededError + if (error.name === 'QuotaExceededError') { + await executeQuotaErrorCallbacks(); + } + throw error; + } + } + for (const callback of this.iterateCallbacks('cacheDidUpdate')) { + await callback({ + cacheName, + oldResponse, + newResponse: responseToCache.clone(), + request: effectiveRequest, + event: this.event + }); + } + return true; + } + /** + * Checks the list of plugins for the `cacheKeyWillBeUsed` callback, and + * executes any of those callbacks found in sequence. The final `Request` + * object returned by the last plugin is treated as the cache key for cache + * reads and/or writes. If no `cacheKeyWillBeUsed` plugin callbacks have + * been registered, the passed request is returned unmodified + * + * @param {Request} request + * @param {string} mode + * @return {Promise} + */ + async getCacheKey(request, mode) { + const key = `${request.url} | ${mode}`; + if (!this._cacheKeys[key]) { + let effectiveRequest = request; + for (const callback of this.iterateCallbacks('cacheKeyWillBeUsed')) { + effectiveRequest = toRequest(await callback({ + mode, + request: effectiveRequest, + event: this.event, + // params has a type any can't change right now. + params: this.params // eslint-disable-line + })); + } + this._cacheKeys[key] = effectiveRequest; + } + return this._cacheKeys[key]; + } + /** + * Returns true if the strategy has at least one plugin with the given + * callback. + * + * @param {string} name The name of the callback to check for. + * @return {boolean} + */ + hasCallback(name) { + for (const plugin of this._strategy.plugins) { + if (name in plugin) { + return true; + } + } + return false; + } + /** + * Runs all plugin callbacks matching the given name, in order, passing the + * given param object (merged ith the current plugin state) as the only + * argument. + * + * Note: since this method runs all plugins, it's not suitable for cases + * where the return value of a callback needs to be applied prior to calling + * the next callback. See + * {@link workbox-strategies.StrategyHandler#iterateCallbacks} + * below for how to handle that case. + * + * @param {string} name The name of the callback to run within each plugin. + * @param {Object} param The object to pass as the first (and only) param + * when executing each callback. This object will be merged with the + * current plugin state prior to callback execution. + */ + async runCallbacks(name, param) { + for (const callback of this.iterateCallbacks(name)) { + // TODO(philipwalton): not sure why `any` is needed. It seems like + // this should work with `as WorkboxPluginCallbackParam[C]`. + await callback(param); + } + } + /** + * Accepts a callback and returns an iterable of matching plugin callbacks, + * where each callback is wrapped with the current handler state (i.e. when + * you call each callback, whatever object parameter you pass it will + * be merged with the plugin's current state). + * + * @param {string} name The name fo the callback to run + * @return {Array} + */ + *iterateCallbacks(name) { + for (const plugin of this._strategy.plugins) { + if (typeof plugin[name] === 'function') { + const state = this._pluginStateMap.get(plugin); + const statefulCallback = param => { + const statefulParam = Object.assign(Object.assign({}, param), { + state + }); + // TODO(philipwalton): not sure why `any` is needed. It seems like + // this should work with `as WorkboxPluginCallbackParam[C]`. + return plugin[name](statefulParam); + }; + yield statefulCallback; + } + } + } + /** + * Adds a promise to the + * [extend lifetime promises]{@link https://w3c.github.io/ServiceWorker/#extendableevent-extend-lifetime-promises} + * of the event associated with the request being handled (usually a + * `FetchEvent`). + * + * Note: you can await + * {@link workbox-strategies.StrategyHandler~doneWaiting} + * to know when all added promises have settled. + * + * @param {Promise} promise A promise to add to the extend lifetime promises + * of the event that triggered the request. + */ + waitUntil(promise) { + this._extendLifetimePromises.push(promise); + return promise; + } + /** + * Returns a promise that resolves once all promises passed to + * {@link workbox-strategies.StrategyHandler~waitUntil} + * have settled. + * + * Note: any work done after `doneWaiting()` settles should be manually + * passed to an event's `waitUntil()` method (not this handler's + * `waitUntil()` method), otherwise the service worker thread may be killed + * prior to your work completing. + */ + async doneWaiting() { + while (this._extendLifetimePromises.length) { + const promises = this._extendLifetimePromises.splice(0); + const result = await Promise.allSettled(promises); + const firstRejection = result.find(i => i.status === 'rejected'); + if (firstRejection) { + throw firstRejection.reason; + } + } + } + /** + * Stops running the strategy and immediately resolves any pending + * `waitUntil()` promises. + */ + destroy() { + this._handlerDeferred.resolve(null); + } + /** + * This method will call cacheWillUpdate on the available plugins (or use + * status === 200) to determine if the Response is safe and valid to cache. + * + * @param {Request} options.request + * @param {Response} options.response + * @return {Promise} + * + * @private + */ + async _ensureResponseSafeToCache(response) { + let responseToCache = response; + let pluginsUsed = false; + for (const callback of this.iterateCallbacks('cacheWillUpdate')) { + responseToCache = (await callback({ + request: this.request, + response: responseToCache, + event: this.event + })) || undefined; + pluginsUsed = true; + if (!responseToCache) { + break; + } + } + if (!pluginsUsed) { + if (responseToCache && responseToCache.status !== 200) { + responseToCache = undefined; + } + { + if (responseToCache) { + if (responseToCache.status !== 200) { + if (responseToCache.status === 0) { + logger.warn(`The response for '${this.request.url}' ` + `is an opaque response. The caching strategy that you're ` + `using will not cache opaque responses by default.`); + } else { + logger.debug(`The response for '${this.request.url}' ` + `returned a status code of '${response.status}' and won't ` + `be cached as a result.`); + } + } + } + } + } + return responseToCache; + } + } + + /* + Copyright 2020 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * An abstract base class that all other strategy classes must extend from: + * + * @memberof workbox-strategies + */ + class Strategy { + /** + * Creates a new instance of the strategy and sets all documented option + * properties as public instance properties. + * + * Note: if a custom strategy class extends the base Strategy class and does + * not need more than these properties, it does not need to define its own + * constructor. + * + * @param {Object} [options] + * @param {string} [options.cacheName] Cache name to store and retrieve + * requests. Defaults to the cache names provided by + * {@link workbox-core.cacheNames}. + * @param {Array} [options.plugins] [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} + * to use in conjunction with this caching strategy. + * @param {Object} [options.fetchOptions] Values passed along to the + * [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) + * of [non-navigation](https://github.com/GoogleChrome/workbox/issues/1796) + * `fetch()` requests made by this strategy. + * @param {Object} [options.matchOptions] The + * [`CacheQueryOptions`]{@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions} + * for any `cache.match()` or `cache.put()` calls made by this strategy. + */ + constructor(options = {}) { + /** + * Cache name to store and retrieve + * requests. Defaults to the cache names provided by + * {@link workbox-core.cacheNames}. + * + * @type {string} + */ + this.cacheName = cacheNames.getRuntimeName(options.cacheName); + /** + * The list + * [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} + * used by this strategy. + * + * @type {Array} + */ + this.plugins = options.plugins || []; + /** + * Values passed along to the + * [`init`]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters} + * of all fetch() requests made by this strategy. + * + * @type {Object} + */ + this.fetchOptions = options.fetchOptions; + /** + * The + * [`CacheQueryOptions`]{@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions} + * for any `cache.match()` or `cache.put()` calls made by this strategy. + * + * @type {Object} + */ + this.matchOptions = options.matchOptions; + } + /** + * Perform a request strategy and returns a `Promise` that will resolve with + * a `Response`, invoking all relevant plugin callbacks. + * + * When a strategy instance is registered with a Workbox + * {@link workbox-routing.Route}, this method is automatically + * called when the route matches. + * + * Alternatively, this method can be used in a standalone `FetchEvent` + * listener by passing it to `event.respondWith()`. + * + * @param {FetchEvent|Object} options A `FetchEvent` or an object with the + * properties listed below. + * @param {Request|string} options.request A request to run this strategy for. + * @param {ExtendableEvent} options.event The event associated with the + * request. + * @param {URL} [options.url] + * @param {*} [options.params] + */ + handle(options) { + const [responseDone] = this.handleAll(options); + return responseDone; + } + /** + * Similar to {@link workbox-strategies.Strategy~handle}, but + * instead of just returning a `Promise` that resolves to a `Response` it + * it will return an tuple of `[response, done]` promises, where the former + * (`response`) is equivalent to what `handle()` returns, and the latter is a + * Promise that will resolve once any promises that were added to + * `event.waitUntil()` as part of performing the strategy have completed. + * + * You can await the `done` promise to ensure any extra work performed by + * the strategy (usually caching responses) completes successfully. + * + * @param {FetchEvent|Object} options A `FetchEvent` or an object with the + * properties listed below. + * @param {Request|string} options.request A request to run this strategy for. + * @param {ExtendableEvent} options.event The event associated with the + * request. + * @param {URL} [options.url] + * @param {*} [options.params] + * @return {Array} A tuple of [response, done] + * promises that can be used to determine when the response resolves as + * well as when the handler has completed all its work. + */ + handleAll(options) { + // Allow for flexible options to be passed. + if (options instanceof FetchEvent) { + options = { + event: options, + request: options.request + }; + } + const event = options.event; + const request = typeof options.request === 'string' ? new Request(options.request) : options.request; + const params = 'params' in options ? options.params : undefined; + const handler = new StrategyHandler(this, { + event, + request, + params + }); + const responseDone = this._getResponse(handler, request, event); + const handlerDone = this._awaitComplete(responseDone, handler, request, event); + // Return an array of promises, suitable for use with Promise.all(). + return [responseDone, handlerDone]; + } + async _getResponse(handler, request, event) { + await handler.runCallbacks('handlerWillStart', { + event, + request + }); + let response = undefined; + try { + response = await this._handle(request, handler); + // The "official" Strategy subclasses all throw this error automatically, + // but in case a third-party Strategy doesn't, ensure that we have a + // consistent failure when there's no response or an error response. + if (!response || response.type === 'error') { + throw new WorkboxError('no-response', { + url: request.url + }); + } + } catch (error) { + if (error instanceof Error) { + for (const callback of handler.iterateCallbacks('handlerDidError')) { + response = await callback({ + error, + event, + request + }); + if (response) { + break; + } + } + } + if (!response) { + throw error; + } else { + logger.log(`While responding to '${getFriendlyURL(request.url)}', ` + `an ${error instanceof Error ? error.toString() : ''} error occurred. Using a fallback response provided by ` + `a handlerDidError plugin.`); + } + } + for (const callback of handler.iterateCallbacks('handlerWillRespond')) { + response = await callback({ + event, + request, + response + }); + } + return response; + } + async _awaitComplete(responseDone, handler, request, event) { + let response; + let error; + try { + response = await responseDone; + } catch (error) { + // Ignore errors, as response errors should be caught via the `response` + // promise above. The `done` promise will only throw for errors in + // promises passed to `handler.waitUntil()`. + } + try { + await handler.runCallbacks('handlerDidRespond', { + event, + request, + response + }); + await handler.doneWaiting(); + } catch (waitUntilError) { + if (waitUntilError instanceof Error) { + error = waitUntilError; + } + } + await handler.runCallbacks('handlerDidComplete', { + event, + request, + response, + error: error + }); + handler.destroy(); + if (error) { + throw error; + } + } + } + /** + * Classes extending the `Strategy` based class should implement this method, + * and leverage the {@link workbox-strategies.StrategyHandler} + * arg to perform all fetching and cache logic, which will ensure all relevant + * cache, cache options, fetch options and plugins are used (per the current + * strategy instance). + * + * @name _handle + * @instance + * @abstract + * @function + * @param {Request} request + * @param {workbox-strategies.StrategyHandler} handler + * @return {Promise} + * + * @memberof workbox-strategies.Strategy + */ + + /* + Copyright 2020 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * A {@link workbox-strategies.Strategy} implementation + * specifically designed to work with + * {@link workbox-precaching.PrecacheController} + * to both cache and fetch precached assets. + * + * Note: an instance of this class is created automatically when creating a + * `PrecacheController`; it's generally not necessary to create this yourself. + * + * @extends workbox-strategies.Strategy + * @memberof workbox-precaching + */ + class PrecacheStrategy extends Strategy { + /** + * + * @param {Object} [options] + * @param {string} [options.cacheName] Cache name to store and retrieve + * requests. Defaults to the cache names provided by + * {@link workbox-core.cacheNames}. + * @param {Array} [options.plugins] {@link https://developers.google.com/web/tools/workbox/guides/using-plugins|Plugins} + * to use in conjunction with this caching strategy. + * @param {Object} [options.fetchOptions] Values passed along to the + * {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters|init} + * of all fetch() requests made by this strategy. + * @param {Object} [options.matchOptions] The + * {@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions|CacheQueryOptions} + * for any `cache.match()` or `cache.put()` calls made by this strategy. + * @param {boolean} [options.fallbackToNetwork=true] Whether to attempt to + * get the response from the network if there's a precache miss. + */ + constructor(options = {}) { + options.cacheName = cacheNames.getPrecacheName(options.cacheName); + super(options); + this._fallbackToNetwork = options.fallbackToNetwork === false ? false : true; + // Redirected responses cannot be used to satisfy a navigation request, so + // any redirected response must be "copied" rather than cloned, so the new + // response doesn't contain the `redirected` flag. See: + // https://bugs.chromium.org/p/chromium/issues/detail?id=669363&desc=2#c1 + this.plugins.push(PrecacheStrategy.copyRedirectedCacheableResponsesPlugin); + } + /** + * @private + * @param {Request|string} request A request to run this strategy for. + * @param {workbox-strategies.StrategyHandler} handler The event that + * triggered the request. + * @return {Promise} + */ + async _handle(request, handler) { + const response = await handler.cacheMatch(request); + if (response) { + return response; + } + // If this is an `install` event for an entry that isn't already cached, + // then populate the cache. + if (handler.event && handler.event.type === 'install') { + return await this._handleInstall(request, handler); + } + // Getting here means something went wrong. An entry that should have been + // precached wasn't found in the cache. + return await this._handleFetch(request, handler); + } + async _handleFetch(request, handler) { + let response; + const params = handler.params || {}; + // Fall back to the network if we're configured to do so. + if (this._fallbackToNetwork) { + { + logger.warn(`The precached response for ` + `${getFriendlyURL(request.url)} in ${this.cacheName} was not ` + `found. Falling back to the network.`); + } + const integrityInManifest = params.integrity; + const integrityInRequest = request.integrity; + const noIntegrityConflict = !integrityInRequest || integrityInRequest === integrityInManifest; + // Do not add integrity if the original request is no-cors + // See https://github.com/GoogleChrome/workbox/issues/3096 + response = await handler.fetch(new Request(request, { + integrity: request.mode !== 'no-cors' ? integrityInRequest || integrityInManifest : undefined + })); + // It's only "safe" to repair the cache if we're using SRI to guarantee + // that the response matches the precache manifest's expectations, + // and there's either a) no integrity property in the incoming request + // or b) there is an integrity, and it matches the precache manifest. + // See https://github.com/GoogleChrome/workbox/issues/2858 + // Also if the original request users no-cors we don't use integrity. + // See https://github.com/GoogleChrome/workbox/issues/3096 + if (integrityInManifest && noIntegrityConflict && request.mode !== 'no-cors') { + this._useDefaultCacheabilityPluginIfNeeded(); + const wasCached = await handler.cachePut(request, response.clone()); + { + if (wasCached) { + logger.log(`A response for ${getFriendlyURL(request.url)} ` + `was used to "repair" the precache.`); + } + } + } + } else { + // This shouldn't normally happen, but there are edge cases: + // https://github.com/GoogleChrome/workbox/issues/1441 + throw new WorkboxError('missing-precache-entry', { + cacheName: this.cacheName, + url: request.url + }); + } + { + const cacheKey = params.cacheKey || (await handler.getCacheKey(request, 'read')); + // Workbox is going to handle the route. + // print the routing details to the console. + logger.groupCollapsed(`Precaching is responding to: ` + getFriendlyURL(request.url)); + logger.log(`Serving the precached url: ${getFriendlyURL(cacheKey instanceof Request ? cacheKey.url : cacheKey)}`); + logger.groupCollapsed(`View request details here.`); + logger.log(request); + logger.groupEnd(); + logger.groupCollapsed(`View response details here.`); + logger.log(response); + logger.groupEnd(); + logger.groupEnd(); + } + return response; + } + async _handleInstall(request, handler) { + this._useDefaultCacheabilityPluginIfNeeded(); + const response = await handler.fetch(request); + // Make sure we defer cachePut() until after we know the response + // should be cached; see https://github.com/GoogleChrome/workbox/issues/2737 + const wasCached = await handler.cachePut(request, response.clone()); + if (!wasCached) { + // Throwing here will lead to the `install` handler failing, which + // we want to do if *any* of the responses aren't safe to cache. + throw new WorkboxError('bad-precaching-response', { + url: request.url, + status: response.status + }); + } + return response; + } + /** + * This method is complex, as there a number of things to account for: + * + * The `plugins` array can be set at construction, and/or it might be added to + * to at any time before the strategy is used. + * + * At the time the strategy is used (i.e. during an `install` event), there + * needs to be at least one plugin that implements `cacheWillUpdate` in the + * array, other than `copyRedirectedCacheableResponsesPlugin`. + * + * - If this method is called and there are no suitable `cacheWillUpdate` + * plugins, we need to add `defaultPrecacheCacheabilityPlugin`. + * + * - If this method is called and there is exactly one `cacheWillUpdate`, then + * we don't have to do anything (this might be a previously added + * `defaultPrecacheCacheabilityPlugin`, or it might be a custom plugin). + * + * - If this method is called and there is more than one `cacheWillUpdate`, + * then we need to check if one is `defaultPrecacheCacheabilityPlugin`. If so, + * we need to remove it. (This situation is unlikely, but it could happen if + * the strategy is used multiple times, the first without a `cacheWillUpdate`, + * and then later on after manually adding a custom `cacheWillUpdate`.) + * + * See https://github.com/GoogleChrome/workbox/issues/2737 for more context. + * + * @private + */ + _useDefaultCacheabilityPluginIfNeeded() { + let defaultPluginIndex = null; + let cacheWillUpdatePluginCount = 0; + for (const [index, plugin] of this.plugins.entries()) { + // Ignore the copy redirected plugin when determining what to do. + if (plugin === PrecacheStrategy.copyRedirectedCacheableResponsesPlugin) { + continue; + } + // Save the default plugin's index, in case it needs to be removed. + if (plugin === PrecacheStrategy.defaultPrecacheCacheabilityPlugin) { + defaultPluginIndex = index; + } + if (plugin.cacheWillUpdate) { + cacheWillUpdatePluginCount++; + } + } + if (cacheWillUpdatePluginCount === 0) { + this.plugins.push(PrecacheStrategy.defaultPrecacheCacheabilityPlugin); + } else if (cacheWillUpdatePluginCount > 1 && defaultPluginIndex !== null) { + // Only remove the default plugin; multiple custom plugins are allowed. + this.plugins.splice(defaultPluginIndex, 1); + } + // Nothing needs to be done if cacheWillUpdatePluginCount is 1 + } + } + PrecacheStrategy.defaultPrecacheCacheabilityPlugin = { + async cacheWillUpdate({ + response + }) { + if (!response || response.status >= 400) { + return null; + } + return response; + } + }; + PrecacheStrategy.copyRedirectedCacheableResponsesPlugin = { + async cacheWillUpdate({ + response + }) { + return response.redirected ? await copyResponse(response) : response; + } + }; + + /* + Copyright 2019 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * Performs efficient precaching of assets. + * + * @memberof workbox-precaching + */ + class PrecacheController { + /** + * Create a new PrecacheController. + * + * @param {Object} [options] + * @param {string} [options.cacheName] The cache to use for precaching. + * @param {string} [options.plugins] Plugins to use when precaching as well + * as responding to fetch events for precached assets. + * @param {boolean} [options.fallbackToNetwork=true] Whether to attempt to + * get the response from the network if there's a precache miss. + */ + constructor({ + cacheName, + plugins = [], + fallbackToNetwork = true + } = {}) { + this._urlsToCacheKeys = new Map(); + this._urlsToCacheModes = new Map(); + this._cacheKeysToIntegrities = new Map(); + this._strategy = new PrecacheStrategy({ + cacheName: cacheNames.getPrecacheName(cacheName), + plugins: [...plugins, new PrecacheCacheKeyPlugin({ + precacheController: this + })], + fallbackToNetwork + }); + // Bind the install and activate methods to the instance. + this.install = this.install.bind(this); + this.activate = this.activate.bind(this); + } + /** + * @type {workbox-precaching.PrecacheStrategy} The strategy created by this controller and + * used to cache assets and respond to fetch events. + */ + get strategy() { + return this._strategy; + } + /** + * Adds items to the precache list, removing any duplicates and + * stores the files in the + * {@link workbox-core.cacheNames|"precache cache"} when the service + * worker installs. + * + * This method can be called multiple times. + * + * @param {Array} [entries=[]] Array of entries to precache. + */ + precache(entries) { + this.addToCacheList(entries); + if (!this._installAndActiveListenersAdded) { + self.addEventListener('install', this.install); + self.addEventListener('activate', this.activate); + this._installAndActiveListenersAdded = true; + } + } + /** + * This method will add items to the precache list, removing duplicates + * and ensuring the information is valid. + * + * @param {Array} entries + * Array of entries to precache. + */ + addToCacheList(entries) { + { + finalAssertExports.isArray(entries, { + moduleName: 'workbox-precaching', + className: 'PrecacheController', + funcName: 'addToCacheList', + paramName: 'entries' + }); + } + const urlsToWarnAbout = []; + for (const entry of entries) { + // See https://github.com/GoogleChrome/workbox/issues/2259 + if (typeof entry === 'string') { + urlsToWarnAbout.push(entry); + } else if (entry && entry.revision === undefined) { + urlsToWarnAbout.push(entry.url); + } + const { + cacheKey, + url + } = createCacheKey(entry); + const cacheMode = typeof entry !== 'string' && entry.revision ? 'reload' : 'default'; + if (this._urlsToCacheKeys.has(url) && this._urlsToCacheKeys.get(url) !== cacheKey) { + throw new WorkboxError('add-to-cache-list-conflicting-entries', { + firstEntry: this._urlsToCacheKeys.get(url), + secondEntry: cacheKey + }); + } + if (typeof entry !== 'string' && entry.integrity) { + if (this._cacheKeysToIntegrities.has(cacheKey) && this._cacheKeysToIntegrities.get(cacheKey) !== entry.integrity) { + throw new WorkboxError('add-to-cache-list-conflicting-integrities', { + url + }); + } + this._cacheKeysToIntegrities.set(cacheKey, entry.integrity); + } + this._urlsToCacheKeys.set(url, cacheKey); + this._urlsToCacheModes.set(url, cacheMode); + if (urlsToWarnAbout.length > 0) { + const warningMessage = `Workbox is precaching URLs without revision ` + `info: ${urlsToWarnAbout.join(', ')}\nThis is generally NOT safe. ` + `Learn more at https://bit.ly/wb-precache`; + { + logger.warn(warningMessage); + } + } + } + } + /** + * Precaches new and updated assets. Call this method from the service worker + * install event. + * + * Note: this method calls `event.waitUntil()` for you, so you do not need + * to call it yourself in your event handlers. + * + * @param {ExtendableEvent} event + * @return {Promise} + */ + install(event) { + // waitUntil returns Promise + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return waitUntil(event, async () => { + const installReportPlugin = new PrecacheInstallReportPlugin(); + this.strategy.plugins.push(installReportPlugin); + // Cache entries one at a time. + // See https://github.com/GoogleChrome/workbox/issues/2528 + for (const [url, cacheKey] of this._urlsToCacheKeys) { + const integrity = this._cacheKeysToIntegrities.get(cacheKey); + const cacheMode = this._urlsToCacheModes.get(url); + const request = new Request(url, { + integrity, + cache: cacheMode, + credentials: 'same-origin' + }); + await Promise.all(this.strategy.handleAll({ + params: { + cacheKey + }, + request, + event + })); + } + const { + updatedURLs, + notUpdatedURLs + } = installReportPlugin; + { + printInstallDetails(updatedURLs, notUpdatedURLs); + } + return { + updatedURLs, + notUpdatedURLs + }; + }); + } + /** + * Deletes assets that are no longer present in the current precache manifest. + * Call this method from the service worker activate event. + * + * Note: this method calls `event.waitUntil()` for you, so you do not need + * to call it yourself in your event handlers. + * + * @param {ExtendableEvent} event + * @return {Promise} + */ + activate(event) { + // waitUntil returns Promise + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return waitUntil(event, async () => { + const cache = await self.caches.open(this.strategy.cacheName); + const currentlyCachedRequests = await cache.keys(); + const expectedCacheKeys = new Set(this._urlsToCacheKeys.values()); + const deletedURLs = []; + for (const request of currentlyCachedRequests) { + if (!expectedCacheKeys.has(request.url)) { + await cache.delete(request); + deletedURLs.push(request.url); + } + } + { + printCleanupDetails(deletedURLs); + } + return { + deletedURLs + }; + }); + } + /** + * Returns a mapping of a precached URL to the corresponding cache key, taking + * into account the revision information for the URL. + * + * @return {Map} A URL to cache key mapping. + */ + getURLsToCacheKeys() { + return this._urlsToCacheKeys; + } + /** + * Returns a list of all the URLs that have been precached by the current + * service worker. + * + * @return {Array} The precached URLs. + */ + getCachedURLs() { + return [...this._urlsToCacheKeys.keys()]; + } + /** + * Returns the cache key used for storing a given URL. If that URL is + * unversioned, like `/index.html', then the cache key will be the original + * URL with a search parameter appended to it. + * + * @param {string} url A URL whose cache key you want to look up. + * @return {string} The versioned URL that corresponds to a cache key + * for the original URL, or undefined if that URL isn't precached. + */ + getCacheKeyForURL(url) { + const urlObject = new URL(url, location.href); + return this._urlsToCacheKeys.get(urlObject.href); + } + /** + * @param {string} url A cache key whose SRI you want to look up. + * @return {string} The subresource integrity associated with the cache key, + * or undefined if it's not set. + */ + getIntegrityForCacheKey(cacheKey) { + return this._cacheKeysToIntegrities.get(cacheKey); + } + /** + * This acts as a drop-in replacement for + * [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match) + * with the following differences: + * + * - It knows what the name of the precache is, and only checks in that cache. + * - It allows you to pass in an "original" URL without versioning parameters, + * and it will automatically look up the correct cache key for the currently + * active revision of that URL. + * + * E.g., `matchPrecache('index.html')` will find the correct precached + * response for the currently active service worker, even if the actual cache + * key is `'/index.html?__WB_REVISION__=1234abcd'`. + * + * @param {string|Request} request The key (without revisioning parameters) + * to look up in the precache. + * @return {Promise} + */ + async matchPrecache(request) { + const url = request instanceof Request ? request.url : request; + const cacheKey = this.getCacheKeyForURL(url); + if (cacheKey) { + const cache = await self.caches.open(this.strategy.cacheName); + return cache.match(cacheKey); + } + return undefined; + } + /** + * Returns a function that looks up `url` in the precache (taking into + * account revision information), and returns the corresponding `Response`. + * + * @param {string} url The precached URL which will be used to lookup the + * `Response`. + * @return {workbox-routing~handlerCallback} + */ + createHandlerBoundToURL(url) { + const cacheKey = this.getCacheKeyForURL(url); + if (!cacheKey) { + throw new WorkboxError('non-precached-url', { + url + }); + } + return options => { + options.request = new Request(url); + options.params = Object.assign({ + cacheKey + }, options.params); + return this.strategy.handle(options); + }; + } + } + + /* + Copyright 2019 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + let precacheController; + /** + * @return {PrecacheController} + * @private + */ + const getOrCreatePrecacheController = () => { + if (!precacheController) { + precacheController = new PrecacheController(); + } + return precacheController; + }; + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * Removes any URL search parameters that should be ignored. + * + * @param {URL} urlObject The original URL. + * @param {Array} ignoreURLParametersMatching RegExps to test against + * each search parameter name. Matches mean that the search parameter should be + * ignored. + * @return {URL} The URL with any ignored search parameters removed. + * + * @private + * @memberof workbox-precaching + */ + function removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching = []) { + // Convert the iterable into an array at the start of the loop to make sure + // deletion doesn't mess up iteration. + for (const paramName of [...urlObject.searchParams.keys()]) { + if (ignoreURLParametersMatching.some(regExp => regExp.test(paramName))) { + urlObject.searchParams.delete(paramName); + } + } + return urlObject; + } + + /* + Copyright 2019 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * Generator function that yields possible variations on the original URL to + * check, one at a time. + * + * @param {string} url + * @param {Object} options + * + * @private + * @memberof workbox-precaching + */ + function* generateURLVariations(url, { + ignoreURLParametersMatching = [/^utm_/, /^fbclid$/], + directoryIndex = 'index.html', + cleanURLs = true, + urlManipulation + } = {}) { + const urlObject = new URL(url, location.href); + urlObject.hash = ''; + yield urlObject.href; + const urlWithoutIgnoredParams = removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching); + yield urlWithoutIgnoredParams.href; + if (directoryIndex && urlWithoutIgnoredParams.pathname.endsWith('/')) { + const directoryURL = new URL(urlWithoutIgnoredParams.href); + directoryURL.pathname += directoryIndex; + yield directoryURL.href; + } + if (cleanURLs) { + const cleanURL = new URL(urlWithoutIgnoredParams.href); + cleanURL.pathname += '.html'; + yield cleanURL.href; + } + if (urlManipulation) { + const additionalURLs = urlManipulation({ + url: urlObject + }); + for (const urlToAttempt of additionalURLs) { + yield urlToAttempt.href; + } + } + } + + /* + Copyright 2020 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * A subclass of {@link workbox-routing.Route} that takes a + * {@link workbox-precaching.PrecacheController} + * instance and uses it to match incoming requests and handle fetching + * responses from the precache. + * + * @memberof workbox-precaching + * @extends workbox-routing.Route + */ + class PrecacheRoute extends Route { + /** + * @param {PrecacheController} precacheController A `PrecacheController` + * instance used to both match requests and respond to fetch events. + * @param {Object} [options] Options to control how requests are matched + * against the list of precached URLs. + * @param {string} [options.directoryIndex=index.html] The `directoryIndex` will + * check cache entries for a URLs ending with '/' to see if there is a hit when + * appending the `directoryIndex` value. + * @param {Array} [options.ignoreURLParametersMatching=[/^utm_/, /^fbclid$/]] An + * array of regex's to remove search params when looking for a cache match. + * @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will + * check the cache for the URL with a `.html` added to the end of the end. + * @param {workbox-precaching~urlManipulation} [options.urlManipulation] + * This is a function that should take a URL and return an array of + * alternative URLs that should be checked for precache matches. + */ + constructor(precacheController, options) { + const match = ({ + request + }) => { + const urlsToCacheKeys = precacheController.getURLsToCacheKeys(); + for (const possibleURL of generateURLVariations(request.url, options)) { + const cacheKey = urlsToCacheKeys.get(possibleURL); + if (cacheKey) { + const integrity = precacheController.getIntegrityForCacheKey(cacheKey); + return { + cacheKey, + integrity + }; + } + } + { + logger.debug(`Precaching did not find a match for ` + getFriendlyURL(request.url)); + } + return; + }; + super(match, precacheController.strategy); + } + } + + /* + Copyright 2019 Google LLC + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * Add a `fetch` listener to the service worker that will + * respond to + * [network requests]{@link https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers#Custom_responses_to_requests} + * with precached assets. + * + * Requests for assets that aren't precached, the `FetchEvent` will not be + * responded to, allowing the event to fall through to other `fetch` event + * listeners. + * + * @param {Object} [options] See the {@link workbox-precaching.PrecacheRoute} + * options. + * + * @memberof workbox-precaching + */ + function addRoute(options) { + const precacheController = getOrCreatePrecacheController(); + const precacheRoute = new PrecacheRoute(precacheController, options); + registerRoute(precacheRoute); + } + + /* + Copyright 2019 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * Adds items to the precache list, removing any duplicates and + * stores the files in the + * {@link workbox-core.cacheNames|"precache cache"} when the service + * worker installs. + * + * This method can be called multiple times. + * + * Please note: This method **will not** serve any of the cached files for you. + * It only precaches files. To respond to a network request you call + * {@link workbox-precaching.addRoute}. + * + * If you have a single array of files to precache, you can just call + * {@link workbox-precaching.precacheAndRoute}. + * + * @param {Array} [entries=[]] Array of entries to precache. + * + * @memberof workbox-precaching + */ + function precache(entries) { + const precacheController = getOrCreatePrecacheController(); + precacheController.precache(entries); + } + + /* + Copyright 2019 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * This method will add entries to the precache list and add a route to + * respond to fetch events. + * + * This is a convenience method that will call + * {@link workbox-precaching.precache} and + * {@link workbox-precaching.addRoute} in a single call. + * + * @param {Array} entries Array of entries to precache. + * @param {Object} [options] See the + * {@link workbox-precaching.PrecacheRoute} options. + * + * @memberof workbox-precaching + */ + function precacheAndRoute(entries, options) { + precache(entries); + addRoute(options); + } + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + const SUBSTRING_TO_FIND = '-precache-'; + /** + * Cleans up incompatible precaches that were created by older versions of + * Workbox, by a service worker registered under the current scope. + * + * This is meant to be called as part of the `activate` event. + * + * This should be safe to use as long as you don't include `substringToFind` + * (defaulting to `-precache-`) in your non-precache cache names. + * + * @param {string} currentPrecacheName The cache name currently in use for + * precaching. This cache won't be deleted. + * @param {string} [substringToFind='-precache-'] Cache names which include this + * substring will be deleted (excluding `currentPrecacheName`). + * @return {Array} A list of all the cache names that were deleted. + * + * @private + * @memberof workbox-precaching + */ + const deleteOutdatedCaches = async (currentPrecacheName, substringToFind = SUBSTRING_TO_FIND) => { + const cacheNames = await self.caches.keys(); + const cacheNamesToDelete = cacheNames.filter(cacheName => { + return cacheName.includes(substringToFind) && cacheName.includes(self.registration.scope) && cacheName !== currentPrecacheName; + }); + await Promise.all(cacheNamesToDelete.map(cacheName => self.caches.delete(cacheName))); + return cacheNamesToDelete; + }; + + /* + Copyright 2019 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * Adds an `activate` event listener which will clean up incompatible + * precaches that were created by older versions of Workbox. + * + * @memberof workbox-precaching + */ + function cleanupOutdatedCaches() { + // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705 + self.addEventListener('activate', event => { + const cacheName = cacheNames.getPrecacheName(); + event.waitUntil(deleteOutdatedCaches(cacheName).then(cachesDeleted => { + { + if (cachesDeleted.length > 0) { + logger.log(`The following out-of-date precaches were cleaned up ` + `automatically:`, cachesDeleted); + } + } + })); + }); + } + + /* + Copyright 2018 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * NavigationRoute makes it easy to create a + * {@link workbox-routing.Route} that matches for browser + * [navigation requests]{@link https://developers.google.com/web/fundamentals/primers/service-workers/high-performance-loading#first_what_are_navigation_requests}. + * + * It will only match incoming Requests whose + * {@link https://fetch.spec.whatwg.org/#concept-request-mode|mode} + * is set to `navigate`. + * + * You can optionally only apply this route to a subset of navigation requests + * by using one or both of the `denylist` and `allowlist` parameters. + * + * @memberof workbox-routing + * @extends workbox-routing.Route + */ + class NavigationRoute extends Route { + /** + * If both `denylist` and `allowlist` are provided, the `denylist` will + * take precedence and the request will not match this route. + * + * The regular expressions in `allowlist` and `denylist` + * are matched against the concatenated + * [`pathname`]{@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/pathname} + * and [`search`]{@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/search} + * portions of the requested URL. + * + * *Note*: These RegExps may be evaluated against every destination URL during + * a navigation. Avoid using + * [complex RegExps](https://github.com/GoogleChrome/workbox/issues/3077), + * or else your users may see delays when navigating your site. + * + * @param {workbox-routing~handlerCallback} handler A callback + * function that returns a Promise resulting in a Response. + * @param {Object} options + * @param {Array} [options.denylist] If any of these patterns match, + * the route will not handle the request (even if a allowlist RegExp matches). + * @param {Array} [options.allowlist=[/./]] If any of these patterns + * match the URL's pathname and search parameter, the route will handle the + * request (assuming the denylist doesn't match). + */ + constructor(handler, { + allowlist = [/./], + denylist = [] + } = {}) { + { + finalAssertExports.isArrayOfClass(allowlist, RegExp, { + moduleName: 'workbox-routing', + className: 'NavigationRoute', + funcName: 'constructor', + paramName: 'options.allowlist' + }); + finalAssertExports.isArrayOfClass(denylist, RegExp, { + moduleName: 'workbox-routing', + className: 'NavigationRoute', + funcName: 'constructor', + paramName: 'options.denylist' + }); + } + super(options => this._match(options), handler); + this._allowlist = allowlist; + this._denylist = denylist; + } + /** + * Routes match handler. + * + * @param {Object} options + * @param {URL} options.url + * @param {Request} options.request + * @return {boolean} + * + * @private + */ + _match({ + url, + request + }) { + if (request && request.mode !== 'navigate') { + return false; + } + const pathnameAndSearch = url.pathname + url.search; + for (const regExp of this._denylist) { + if (regExp.test(pathnameAndSearch)) { + { + logger.log(`The navigation route ${pathnameAndSearch} is not ` + `being used, since the URL matches this denylist pattern: ` + `${regExp.toString()}`); + } + return false; + } + } + if (this._allowlist.some(regExp => regExp.test(pathnameAndSearch))) { + { + logger.debug(`The navigation route ${pathnameAndSearch} ` + `is being used.`); + } + return true; + } + { + logger.log(`The navigation route ${pathnameAndSearch} is not ` + `being used, since the URL being navigated to doesn't ` + `match the allowlist.`); + } + return false; + } + } + + /* + Copyright 2019 Google LLC + + Use of this source code is governed by an MIT-style + license that can be found in the LICENSE file or at + https://opensource.org/licenses/MIT. + */ + /** + * Helper function that calls + * {@link PrecacheController#createHandlerBoundToURL} on the default + * {@link PrecacheController} instance. + * + * If you are creating your own {@link PrecacheController}, then call the + * {@link PrecacheController#createHandlerBoundToURL} on that instance, + * instead of using this function. + * + * @param {string} url The precached URL which will be used to lookup the + * `Response`. + * @param {boolean} [fallbackToNetwork=true] Whether to attempt to get the + * response from the network if there's a precache miss. + * @return {workbox-routing~handlerCallback} + * + * @memberof workbox-precaching + */ + function createHandlerBoundToURL(url) { + const precacheController = getOrCreatePrecacheController(); + return precacheController.createHandlerBoundToURL(url); + } + + exports.NavigationRoute = NavigationRoute; + exports.cleanupOutdatedCaches = cleanupOutdatedCaches; + exports.clientsClaim = clientsClaim; + exports.createHandlerBoundToURL = createHandlerBoundToURL; + exports.precacheAndRoute = precacheAndRoute; + exports.registerRoute = registerRoute; + +})); From 2aaf308640a0e13b355f1d58ffc7ee956f13244d Mon Sep 17 00:00:00 2001 From: Alessandro Falezza Date: Mon, 22 Dec 2025 15:10:17 +0100 Subject: [PATCH 5/6] untrack dev dist --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index ce67f489..3719a7a2 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,7 @@ lerna-debug.log* node_modules dist dist-electron +dev-dist db/* !db/.gitkeep release From 318e903c4ae2171163b8e4d0aa58c2d6ebfae68a Mon Sep 17 00:00:00 2001 From: Alessandro Falezza Date: Mon, 22 Dec 2025 15:14:49 +0100 Subject: [PATCH 6/6] Remove dev dist from git --- dev-dist/registerSW.js | 1 - dev-dist/sw.js | 92 - dev-dist/workbox-5a5d9309.js | 3395 ---------------------------------- 3 files changed, 3488 deletions(-) delete mode 100644 dev-dist/registerSW.js delete mode 100644 dev-dist/sw.js delete mode 100644 dev-dist/workbox-5a5d9309.js diff --git a/dev-dist/registerSW.js b/dev-dist/registerSW.js deleted file mode 100644 index 1d5625f4..00000000 --- a/dev-dist/registerSW.js +++ /dev/null @@ -1 +0,0 @@ -if('serviceWorker' in navigator) navigator.serviceWorker.register('/dev-sw.js?dev-sw', { scope: '/', type: 'classic' }) \ No newline at end of file diff --git a/dev-dist/sw.js b/dev-dist/sw.js deleted file mode 100644 index 47374948..00000000 --- a/dev-dist/sw.js +++ /dev/null @@ -1,92 +0,0 @@ -/** - * Copyright 2018 Google Inc. All Rights Reserved. - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -// If the loader is already loaded, just stop. -if (!self.define) { - let registry = {}; - - // Used for `eval` and `importScripts` where we can't get script URL by other means. - // In both cases, it's safe to use a global var because those functions are synchronous. - let nextDefineUri; - - const singleRequire = (uri, parentUri) => { - uri = new URL(uri + ".js", parentUri).href; - return registry[uri] || ( - - new Promise(resolve => { - if ("document" in self) { - const script = document.createElement("script"); - script.src = uri; - script.onload = resolve; - document.head.appendChild(script); - } else { - nextDefineUri = uri; - importScripts(uri); - resolve(); - } - }) - - .then(() => { - let promise = registry[uri]; - if (!promise) { - throw new Error(`Module ${uri} didn’t register its module`); - } - return promise; - }) - ); - }; - - self.define = (depsNames, factory) => { - const uri = nextDefineUri || ("document" in self ? document.currentScript.src : "") || location.href; - if (registry[uri]) { - // Module is already loading or loaded. - return; - } - let exports = {}; - const require = depUri => singleRequire(depUri, uri); - const specialDeps = { - module: { uri }, - exports, - require - }; - registry[uri] = Promise.all(depsNames.map( - depName => specialDeps[depName] || require(depName) - )).then(deps => { - factory(...deps); - return exports; - }); - }; -} -define(['./workbox-5a5d9309'], (function (workbox) { 'use strict'; - - self.skipWaiting(); - workbox.clientsClaim(); - - /** - * The precacheAndRoute() method efficiently caches and responds to - * requests for URLs in the manifest. - * See https://goo.gl/S9QRab - */ - workbox.precacheAndRoute([{ - "url": "registerSW.js", - "revision": "3ca0b8505b4bec776b69afdba2768812" - }, { - "url": "index.html", - "revision": "0.05d2ranheq8" - }], {}); - workbox.cleanupOutdatedCaches(); - workbox.registerRoute(new workbox.NavigationRoute(workbox.createHandlerBoundToURL("index.html"), { - allowlist: [/^\/$/] - })); - -})); diff --git a/dev-dist/workbox-5a5d9309.js b/dev-dist/workbox-5a5d9309.js deleted file mode 100644 index 6f2a448e..00000000 --- a/dev-dist/workbox-5a5d9309.js +++ /dev/null @@ -1,3395 +0,0 @@ -define(['exports'], (function (exports) { 'use strict'; - - // @ts-ignore - try { - self['workbox:core:7.3.0'] && _(); - } catch (e) {} - - /* - Copyright 2019 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * Claim any currently available clients once the service worker - * becomes active. This is normally used in conjunction with `skipWaiting()`. - * - * @memberof workbox-core - */ - function clientsClaim() { - self.addEventListener('activate', () => self.clients.claim()); - } - - /* - Copyright 2019 Google LLC - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - const logger = (() => { - // Don't overwrite this value if it's already set. - // See https://github.com/GoogleChrome/workbox/pull/2284#issuecomment-560470923 - if (!('__WB_DISABLE_DEV_LOGS' in globalThis)) { - self.__WB_DISABLE_DEV_LOGS = false; - } - let inGroup = false; - const methodToColorMap = { - debug: `#7f8c8d`, - log: `#2ecc71`, - warn: `#f39c12`, - error: `#c0392b`, - groupCollapsed: `#3498db`, - groupEnd: null // No colored prefix on groupEnd - }; - const print = function (method, args) { - if (self.__WB_DISABLE_DEV_LOGS) { - return; - } - if (method === 'groupCollapsed') { - // Safari doesn't print all console.groupCollapsed() arguments: - // https://bugs.webkit.org/show_bug.cgi?id=182754 - if (/^((?!chrome|android).)*safari/i.test(navigator.userAgent)) { - console[method](...args); - return; - } - } - const styles = [`background: ${methodToColorMap[method]}`, `border-radius: 0.5em`, `color: white`, `font-weight: bold`, `padding: 2px 0.5em`]; - // When in a group, the workbox prefix is not displayed. - const logPrefix = inGroup ? [] : ['%cworkbox', styles.join(';')]; - console[method](...logPrefix, ...args); - if (method === 'groupCollapsed') { - inGroup = true; - } - if (method === 'groupEnd') { - inGroup = false; - } - }; - // eslint-disable-next-line @typescript-eslint/ban-types - const api = {}; - const loggerMethods = Object.keys(methodToColorMap); - for (const key of loggerMethods) { - const method = key; - api[method] = (...args) => { - print(method, args); - }; - } - return api; - })(); - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - const messages = { - 'invalid-value': ({ - paramName, - validValueDescription, - value - }) => { - if (!paramName || !validValueDescription) { - throw new Error(`Unexpected input to 'invalid-value' error.`); - } - return `The '${paramName}' parameter was given a value with an ` + `unexpected value. ${validValueDescription} Received a value of ` + `${JSON.stringify(value)}.`; - }, - 'not-an-array': ({ - moduleName, - className, - funcName, - paramName - }) => { - if (!moduleName || !className || !funcName || !paramName) { - throw new Error(`Unexpected input to 'not-an-array' error.`); - } - return `The parameter '${paramName}' passed into ` + `'${moduleName}.${className}.${funcName}()' must be an array.`; - }, - 'incorrect-type': ({ - expectedType, - paramName, - moduleName, - className, - funcName - }) => { - if (!expectedType || !paramName || !moduleName || !funcName) { - throw new Error(`Unexpected input to 'incorrect-type' error.`); - } - const classNameStr = className ? `${className}.` : ''; - return `The parameter '${paramName}' passed into ` + `'${moduleName}.${classNameStr}` + `${funcName}()' must be of type ${expectedType}.`; - }, - 'incorrect-class': ({ - expectedClassName, - paramName, - moduleName, - className, - funcName, - isReturnValueProblem - }) => { - if (!expectedClassName || !moduleName || !funcName) { - throw new Error(`Unexpected input to 'incorrect-class' error.`); - } - const classNameStr = className ? `${className}.` : ''; - if (isReturnValueProblem) { - return `The return value from ` + `'${moduleName}.${classNameStr}${funcName}()' ` + `must be an instance of class ${expectedClassName}.`; - } - return `The parameter '${paramName}' passed into ` + `'${moduleName}.${classNameStr}${funcName}()' ` + `must be an instance of class ${expectedClassName}.`; - }, - 'missing-a-method': ({ - expectedMethod, - paramName, - moduleName, - className, - funcName - }) => { - if (!expectedMethod || !paramName || !moduleName || !className || !funcName) { - throw new Error(`Unexpected input to 'missing-a-method' error.`); - } - return `${moduleName}.${className}.${funcName}() expected the ` + `'${paramName}' parameter to expose a '${expectedMethod}' method.`; - }, - 'add-to-cache-list-unexpected-type': ({ - entry - }) => { - return `An unexpected entry was passed to ` + `'workbox-precaching.PrecacheController.addToCacheList()' The entry ` + `'${JSON.stringify(entry)}' isn't supported. You must supply an array of ` + `strings with one or more characters, objects with a url property or ` + `Request objects.`; - }, - 'add-to-cache-list-conflicting-entries': ({ - firstEntry, - secondEntry - }) => { - if (!firstEntry || !secondEntry) { - throw new Error(`Unexpected input to ` + `'add-to-cache-list-duplicate-entries' error.`); - } - return `Two of the entries passed to ` + `'workbox-precaching.PrecacheController.addToCacheList()' had the URL ` + `${firstEntry} but different revision details. Workbox is ` + `unable to cache and version the asset correctly. Please remove one ` + `of the entries.`; - }, - 'plugin-error-request-will-fetch': ({ - thrownErrorMessage - }) => { - if (!thrownErrorMessage) { - throw new Error(`Unexpected input to ` + `'plugin-error-request-will-fetch', error.`); - } - return `An error was thrown by a plugins 'requestWillFetch()' method. ` + `The thrown error message was: '${thrownErrorMessage}'.`; - }, - 'invalid-cache-name': ({ - cacheNameId, - value - }) => { - if (!cacheNameId) { - throw new Error(`Expected a 'cacheNameId' for error 'invalid-cache-name'`); - } - return `You must provide a name containing at least one character for ` + `setCacheDetails({${cacheNameId}: '...'}). Received a value of ` + `'${JSON.stringify(value)}'`; - }, - 'unregister-route-but-not-found-with-method': ({ - method - }) => { - if (!method) { - throw new Error(`Unexpected input to ` + `'unregister-route-but-not-found-with-method' error.`); - } - return `The route you're trying to unregister was not previously ` + `registered for the method type '${method}'.`; - }, - 'unregister-route-route-not-registered': () => { - return `The route you're trying to unregister was not previously ` + `registered.`; - }, - 'queue-replay-failed': ({ - name - }) => { - return `Replaying the background sync queue '${name}' failed.`; - }, - 'duplicate-queue-name': ({ - name - }) => { - return `The Queue name '${name}' is already being used. ` + `All instances of backgroundSync.Queue must be given unique names.`; - }, - 'expired-test-without-max-age': ({ - methodName, - paramName - }) => { - return `The '${methodName}()' method can only be used when the ` + `'${paramName}' is used in the constructor.`; - }, - 'unsupported-route-type': ({ - moduleName, - className, - funcName, - paramName - }) => { - return `The supplied '${paramName}' parameter was an unsupported type. ` + `Please check the docs for ${moduleName}.${className}.${funcName} for ` + `valid input types.`; - }, - 'not-array-of-class': ({ - value, - expectedClass, - moduleName, - className, - funcName, - paramName - }) => { - return `The supplied '${paramName}' parameter must be an array of ` + `'${expectedClass}' objects. Received '${JSON.stringify(value)},'. ` + `Please check the call to ${moduleName}.${className}.${funcName}() ` + `to fix the issue.`; - }, - 'max-entries-or-age-required': ({ - moduleName, - className, - funcName - }) => { - return `You must define either config.maxEntries or config.maxAgeSeconds` + `in ${moduleName}.${className}.${funcName}`; - }, - 'statuses-or-headers-required': ({ - moduleName, - className, - funcName - }) => { - return `You must define either config.statuses or config.headers` + `in ${moduleName}.${className}.${funcName}`; - }, - 'invalid-string': ({ - moduleName, - funcName, - paramName - }) => { - if (!paramName || !moduleName || !funcName) { - throw new Error(`Unexpected input to 'invalid-string' error.`); - } - return `When using strings, the '${paramName}' parameter must start with ` + `'http' (for cross-origin matches) or '/' (for same-origin matches). ` + `Please see the docs for ${moduleName}.${funcName}() for ` + `more info.`; - }, - 'channel-name-required': () => { - return `You must provide a channelName to construct a ` + `BroadcastCacheUpdate instance.`; - }, - 'invalid-responses-are-same-args': () => { - return `The arguments passed into responsesAreSame() appear to be ` + `invalid. Please ensure valid Responses are used.`; - }, - 'expire-custom-caches-only': () => { - return `You must provide a 'cacheName' property when using the ` + `expiration plugin with a runtime caching strategy.`; - }, - 'unit-must-be-bytes': ({ - normalizedRangeHeader - }) => { - if (!normalizedRangeHeader) { - throw new Error(`Unexpected input to 'unit-must-be-bytes' error.`); - } - return `The 'unit' portion of the Range header must be set to 'bytes'. ` + `The Range header provided was "${normalizedRangeHeader}"`; - }, - 'single-range-only': ({ - normalizedRangeHeader - }) => { - if (!normalizedRangeHeader) { - throw new Error(`Unexpected input to 'single-range-only' error.`); - } - return `Multiple ranges are not supported. Please use a single start ` + `value, and optional end value. The Range header provided was ` + `"${normalizedRangeHeader}"`; - }, - 'invalid-range-values': ({ - normalizedRangeHeader - }) => { - if (!normalizedRangeHeader) { - throw new Error(`Unexpected input to 'invalid-range-values' error.`); - } - return `The Range header is missing both start and end values. At least ` + `one of those values is needed. The Range header provided was ` + `"${normalizedRangeHeader}"`; - }, - 'no-range-header': () => { - return `No Range header was found in the Request provided.`; - }, - 'range-not-satisfiable': ({ - size, - start, - end - }) => { - return `The start (${start}) and end (${end}) values in the Range are ` + `not satisfiable by the cached response, which is ${size} bytes.`; - }, - 'attempt-to-cache-non-get-request': ({ - url, - method - }) => { - return `Unable to cache '${url}' because it is a '${method}' request and ` + `only 'GET' requests can be cached.`; - }, - 'cache-put-with-no-response': ({ - url - }) => { - return `There was an attempt to cache '${url}' but the response was not ` + `defined.`; - }, - 'no-response': ({ - url, - error - }) => { - let message = `The strategy could not generate a response for '${url}'.`; - if (error) { - message += ` The underlying error is ${error}.`; - } - return message; - }, - 'bad-precaching-response': ({ - url, - status - }) => { - return `The precaching request for '${url}' failed` + (status ? ` with an HTTP status of ${status}.` : `.`); - }, - 'non-precached-url': ({ - url - }) => { - return `createHandlerBoundToURL('${url}') was called, but that URL is ` + `not precached. Please pass in a URL that is precached instead.`; - }, - 'add-to-cache-list-conflicting-integrities': ({ - url - }) => { - return `Two of the entries passed to ` + `'workbox-precaching.PrecacheController.addToCacheList()' had the URL ` + `${url} with different integrity values. Please remove one of them.`; - }, - 'missing-precache-entry': ({ - cacheName, - url - }) => { - return `Unable to find a precached response in ${cacheName} for ${url}.`; - }, - 'cross-origin-copy-response': ({ - origin - }) => { - return `workbox-core.copyResponse() can only be used with same-origin ` + `responses. It was passed a response with origin ${origin}.`; - }, - 'opaque-streams-source': ({ - type - }) => { - const message = `One of the workbox-streams sources resulted in an ` + `'${type}' response.`; - if (type === 'opaqueredirect') { - return `${message} Please do not use a navigation request that results ` + `in a redirect as a source.`; - } - return `${message} Please ensure your sources are CORS-enabled.`; - } - }; - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - const generatorFunction = (code, details = {}) => { - const message = messages[code]; - if (!message) { - throw new Error(`Unable to find message for code '${code}'.`); - } - return message(details); - }; - const messageGenerator = generatorFunction; - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * Workbox errors should be thrown with this class. - * This allows use to ensure the type easily in tests, - * helps developers identify errors from workbox - * easily and allows use to optimise error - * messages correctly. - * - * @private - */ - class WorkboxError extends Error { - /** - * - * @param {string} errorCode The error code that - * identifies this particular error. - * @param {Object=} details Any relevant arguments - * that will help developers identify issues should - * be added as a key on the context object. - */ - constructor(errorCode, details) { - const message = messageGenerator(errorCode, details); - super(message); - this.name = errorCode; - this.details = details; - } - } - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /* - * This method throws if the supplied value is not an array. - * The destructed values are required to produce a meaningful error for users. - * The destructed and restructured object is so it's clear what is - * needed. - */ - const isArray = (value, details) => { - if (!Array.isArray(value)) { - throw new WorkboxError('not-an-array', details); - } - }; - const hasMethod = (object, expectedMethod, details) => { - const type = typeof object[expectedMethod]; - if (type !== 'function') { - details['expectedMethod'] = expectedMethod; - throw new WorkboxError('missing-a-method', details); - } - }; - const isType = (object, expectedType, details) => { - if (typeof object !== expectedType) { - details['expectedType'] = expectedType; - throw new WorkboxError('incorrect-type', details); - } - }; - const isInstance = (object, - // Need the general type to do the check later. - // eslint-disable-next-line @typescript-eslint/ban-types - expectedClass, details) => { - if (!(object instanceof expectedClass)) { - details['expectedClassName'] = expectedClass.name; - throw new WorkboxError('incorrect-class', details); - } - }; - const isOneOf = (value, validValues, details) => { - if (!validValues.includes(value)) { - details['validValueDescription'] = `Valid values are ${JSON.stringify(validValues)}.`; - throw new WorkboxError('invalid-value', details); - } - }; - const isArrayOfClass = (value, - // Need general type to do check later. - expectedClass, - // eslint-disable-line - details) => { - const error = new WorkboxError('not-array-of-class', details); - if (!Array.isArray(value)) { - throw error; - } - for (const item of value) { - if (!(item instanceof expectedClass)) { - throw error; - } - } - }; - const finalAssertExports = { - hasMethod, - isArray, - isInstance, - isOneOf, - isType, - isArrayOfClass - }; - - // @ts-ignore - try { - self['workbox:routing:7.3.0'] && _(); - } catch (e) {} - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * The default HTTP method, 'GET', used when there's no specific method - * configured for a route. - * - * @type {string} - * - * @private - */ - const defaultMethod = 'GET'; - /** - * The list of valid HTTP methods associated with requests that could be routed. - * - * @type {Array} - * - * @private - */ - const validMethods = ['DELETE', 'GET', 'HEAD', 'PATCH', 'POST', 'PUT']; - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * @param {function()|Object} handler Either a function, or an object with a - * 'handle' method. - * @return {Object} An object with a handle method. - * - * @private - */ - const normalizeHandler = handler => { - if (handler && typeof handler === 'object') { - { - finalAssertExports.hasMethod(handler, 'handle', { - moduleName: 'workbox-routing', - className: 'Route', - funcName: 'constructor', - paramName: 'handler' - }); - } - return handler; - } else { - { - finalAssertExports.isType(handler, 'function', { - moduleName: 'workbox-routing', - className: 'Route', - funcName: 'constructor', - paramName: 'handler' - }); - } - return { - handle: handler - }; - } - }; - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * A `Route` consists of a pair of callback functions, "match" and "handler". - * The "match" callback determine if a route should be used to "handle" a - * request by returning a non-falsy value if it can. The "handler" callback - * is called when there is a match and should return a Promise that resolves - * to a `Response`. - * - * @memberof workbox-routing - */ - class Route { - /** - * Constructor for Route class. - * - * @param {workbox-routing~matchCallback} match - * A callback function that determines whether the route matches a given - * `fetch` event by returning a non-falsy value. - * @param {workbox-routing~handlerCallback} handler A callback - * function that returns a Promise resolving to a Response. - * @param {string} [method='GET'] The HTTP method to match the Route - * against. - */ - constructor(match, handler, method = defaultMethod) { - { - finalAssertExports.isType(match, 'function', { - moduleName: 'workbox-routing', - className: 'Route', - funcName: 'constructor', - paramName: 'match' - }); - if (method) { - finalAssertExports.isOneOf(method, validMethods, { - paramName: 'method' - }); - } - } - // These values are referenced directly by Router so cannot be - // altered by minificaton. - this.handler = normalizeHandler(handler); - this.match = match; - this.method = method; - } - /** - * - * @param {workbox-routing-handlerCallback} handler A callback - * function that returns a Promise resolving to a Response - */ - setCatchHandler(handler) { - this.catchHandler = normalizeHandler(handler); - } - } - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * RegExpRoute makes it easy to create a regular expression based - * {@link workbox-routing.Route}. - * - * For same-origin requests the RegExp only needs to match part of the URL. For - * requests against third-party servers, you must define a RegExp that matches - * the start of the URL. - * - * @memberof workbox-routing - * @extends workbox-routing.Route - */ - class RegExpRoute extends Route { - /** - * If the regular expression contains - * [capture groups]{@link https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp#grouping-back-references}, - * the captured values will be passed to the - * {@link workbox-routing~handlerCallback} `params` - * argument. - * - * @param {RegExp} regExp The regular expression to match against URLs. - * @param {workbox-routing~handlerCallback} handler A callback - * function that returns a Promise resulting in a Response. - * @param {string} [method='GET'] The HTTP method to match the Route - * against. - */ - constructor(regExp, handler, method) { - { - finalAssertExports.isInstance(regExp, RegExp, { - moduleName: 'workbox-routing', - className: 'RegExpRoute', - funcName: 'constructor', - paramName: 'pattern' - }); - } - const match = ({ - url - }) => { - const result = regExp.exec(url.href); - // Return immediately if there's no match. - if (!result) { - return; - } - // Require that the match start at the first character in the URL string - // if it's a cross-origin request. - // See https://github.com/GoogleChrome/workbox/issues/281 for the context - // behind this behavior. - if (url.origin !== location.origin && result.index !== 0) { - { - logger.debug(`The regular expression '${regExp.toString()}' only partially matched ` + `against the cross-origin URL '${url.toString()}'. RegExpRoute's will only ` + `handle cross-origin requests if they match the entire URL.`); - } - return; - } - // If the route matches, but there aren't any capture groups defined, then - // this will return [], which is truthy and therefore sufficient to - // indicate a match. - // If there are capture groups, then it will return their values. - return result.slice(1); - }; - super(match, handler, method); - } - } - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - const getFriendlyURL = url => { - const urlObj = new URL(String(url), location.href); - // See https://github.com/GoogleChrome/workbox/issues/2323 - // We want to include everything, except for the origin if it's same-origin. - return urlObj.href.replace(new RegExp(`^${location.origin}`), ''); - }; - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * The Router can be used to process a `FetchEvent` using one or more - * {@link workbox-routing.Route}, responding with a `Response` if - * a matching route exists. - * - * If no route matches a given a request, the Router will use a "default" - * handler if one is defined. - * - * Should the matching Route throw an error, the Router will use a "catch" - * handler if one is defined to gracefully deal with issues and respond with a - * Request. - * - * If a request matches multiple routes, the **earliest** registered route will - * be used to respond to the request. - * - * @memberof workbox-routing - */ - class Router { - /** - * Initializes a new Router. - */ - constructor() { - this._routes = new Map(); - this._defaultHandlerMap = new Map(); - } - /** - * @return {Map>} routes A `Map` of HTTP - * method name ('GET', etc.) to an array of all the corresponding `Route` - * instances that are registered. - */ - get routes() { - return this._routes; - } - /** - * Adds a fetch event listener to respond to events when a route matches - * the event's request. - */ - addFetchListener() { - // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705 - self.addEventListener('fetch', event => { - const { - request - } = event; - const responsePromise = this.handleRequest({ - request, - event - }); - if (responsePromise) { - event.respondWith(responsePromise); - } - }); - } - /** - * Adds a message event listener for URLs to cache from the window. - * This is useful to cache resources loaded on the page prior to when the - * service worker started controlling it. - * - * The format of the message data sent from the window should be as follows. - * Where the `urlsToCache` array may consist of URL strings or an array of - * URL string + `requestInit` object (the same as you'd pass to `fetch()`). - * - * ``` - * { - * type: 'CACHE_URLS', - * payload: { - * urlsToCache: [ - * './script1.js', - * './script2.js', - * ['./script3.js', {mode: 'no-cors'}], - * ], - * }, - * } - * ``` - */ - addCacheListener() { - // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705 - self.addEventListener('message', event => { - // event.data is type 'any' - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (event.data && event.data.type === 'CACHE_URLS') { - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const { - payload - } = event.data; - { - logger.debug(`Caching URLs from the window`, payload.urlsToCache); - } - const requestPromises = Promise.all(payload.urlsToCache.map(entry => { - if (typeof entry === 'string') { - entry = [entry]; - } - const request = new Request(...entry); - return this.handleRequest({ - request, - event - }); - // TODO(philipwalton): TypeScript errors without this typecast for - // some reason (probably a bug). The real type here should work but - // doesn't: `Array | undefined>`. - })); // TypeScript - event.waitUntil(requestPromises); - // If a MessageChannel was used, reply to the message on success. - if (event.ports && event.ports[0]) { - void requestPromises.then(() => event.ports[0].postMessage(true)); - } - } - }); - } - /** - * Apply the routing rules to a FetchEvent object to get a Response from an - * appropriate Route's handler. - * - * @param {Object} options - * @param {Request} options.request The request to handle. - * @param {ExtendableEvent} options.event The event that triggered the - * request. - * @return {Promise|undefined} A promise is returned if a - * registered route can handle the request. If there is no matching - * route and there's no `defaultHandler`, `undefined` is returned. - */ - handleRequest({ - request, - event - }) { - { - finalAssertExports.isInstance(request, Request, { - moduleName: 'workbox-routing', - className: 'Router', - funcName: 'handleRequest', - paramName: 'options.request' - }); - } - const url = new URL(request.url, location.href); - if (!url.protocol.startsWith('http')) { - { - logger.debug(`Workbox Router only supports URLs that start with 'http'.`); - } - return; - } - const sameOrigin = url.origin === location.origin; - const { - params, - route - } = this.findMatchingRoute({ - event, - request, - sameOrigin, - url - }); - let handler = route && route.handler; - const debugMessages = []; - { - if (handler) { - debugMessages.push([`Found a route to handle this request:`, route]); - if (params) { - debugMessages.push([`Passing the following params to the route's handler:`, params]); - } - } - } - // If we don't have a handler because there was no matching route, then - // fall back to defaultHandler if that's defined. - const method = request.method; - if (!handler && this._defaultHandlerMap.has(method)) { - { - debugMessages.push(`Failed to find a matching route. Falling ` + `back to the default handler for ${method}.`); - } - handler = this._defaultHandlerMap.get(method); - } - if (!handler) { - { - // No handler so Workbox will do nothing. If logs is set of debug - // i.e. verbose, we should print out this information. - logger.debug(`No route found for: ${getFriendlyURL(url)}`); - } - return; - } - { - // We have a handler, meaning Workbox is going to handle the route. - // print the routing details to the console. - logger.groupCollapsed(`Router is responding to: ${getFriendlyURL(url)}`); - debugMessages.forEach(msg => { - if (Array.isArray(msg)) { - logger.log(...msg); - } else { - logger.log(msg); - } - }); - logger.groupEnd(); - } - // Wrap in try and catch in case the handle method throws a synchronous - // error. It should still callback to the catch handler. - let responsePromise; - try { - responsePromise = handler.handle({ - url, - request, - event, - params - }); - } catch (err) { - responsePromise = Promise.reject(err); - } - // Get route's catch handler, if it exists - const catchHandler = route && route.catchHandler; - if (responsePromise instanceof Promise && (this._catchHandler || catchHandler)) { - responsePromise = responsePromise.catch(async err => { - // If there's a route catch handler, process that first - if (catchHandler) { - { - // Still include URL here as it will be async from the console group - // and may not make sense without the URL - logger.groupCollapsed(`Error thrown when responding to: ` + ` ${getFriendlyURL(url)}. Falling back to route's Catch Handler.`); - logger.error(`Error thrown by:`, route); - logger.error(err); - logger.groupEnd(); - } - try { - return await catchHandler.handle({ - url, - request, - event, - params - }); - } catch (catchErr) { - if (catchErr instanceof Error) { - err = catchErr; - } - } - } - if (this._catchHandler) { - { - // Still include URL here as it will be async from the console group - // and may not make sense without the URL - logger.groupCollapsed(`Error thrown when responding to: ` + ` ${getFriendlyURL(url)}. Falling back to global Catch Handler.`); - logger.error(`Error thrown by:`, route); - logger.error(err); - logger.groupEnd(); - } - return this._catchHandler.handle({ - url, - request, - event - }); - } - throw err; - }); - } - return responsePromise; - } - /** - * Checks a request and URL (and optionally an event) against the list of - * registered routes, and if there's a match, returns the corresponding - * route along with any params generated by the match. - * - * @param {Object} options - * @param {URL} options.url - * @param {boolean} options.sameOrigin The result of comparing `url.origin` - * against the current origin. - * @param {Request} options.request The request to match. - * @param {Event} options.event The corresponding event. - * @return {Object} An object with `route` and `params` properties. - * They are populated if a matching route was found or `undefined` - * otherwise. - */ - findMatchingRoute({ - url, - sameOrigin, - request, - event - }) { - const routes = this._routes.get(request.method) || []; - for (const route of routes) { - let params; - // route.match returns type any, not possible to change right now. - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - const matchResult = route.match({ - url, - sameOrigin, - request, - event - }); - if (matchResult) { - { - // Warn developers that using an async matchCallback is almost always - // not the right thing to do. - if (matchResult instanceof Promise) { - logger.warn(`While routing ${getFriendlyURL(url)}, an async ` + `matchCallback function was used. Please convert the ` + `following route to use a synchronous matchCallback function:`, route); - } - } - // See https://github.com/GoogleChrome/workbox/issues/2079 - // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment - params = matchResult; - if (Array.isArray(params) && params.length === 0) { - // Instead of passing an empty array in as params, use undefined. - params = undefined; - } else if (matchResult.constructor === Object && - // eslint-disable-line - Object.keys(matchResult).length === 0) { - // Instead of passing an empty object in as params, use undefined. - params = undefined; - } else if (typeof matchResult === 'boolean') { - // For the boolean value true (rather than just something truth-y), - // don't set params. - // See https://github.com/GoogleChrome/workbox/pull/2134#issuecomment-513924353 - params = undefined; - } - // Return early if have a match. - return { - route, - params - }; - } - } - // If no match was found above, return and empty object. - return {}; - } - /** - * Define a default `handler` that's called when no routes explicitly - * match the incoming request. - * - * Each HTTP method ('GET', 'POST', etc.) gets its own default handler. - * - * Without a default handler, unmatched requests will go against the - * network as if there were no service worker present. - * - * @param {workbox-routing~handlerCallback} handler A callback - * function that returns a Promise resulting in a Response. - * @param {string} [method='GET'] The HTTP method to associate with this - * default handler. Each method has its own default. - */ - setDefaultHandler(handler, method = defaultMethod) { - this._defaultHandlerMap.set(method, normalizeHandler(handler)); - } - /** - * If a Route throws an error while handling a request, this `handler` - * will be called and given a chance to provide a response. - * - * @param {workbox-routing~handlerCallback} handler A callback - * function that returns a Promise resulting in a Response. - */ - setCatchHandler(handler) { - this._catchHandler = normalizeHandler(handler); - } - /** - * Registers a route with the router. - * - * @param {workbox-routing.Route} route The route to register. - */ - registerRoute(route) { - { - finalAssertExports.isType(route, 'object', { - moduleName: 'workbox-routing', - className: 'Router', - funcName: 'registerRoute', - paramName: 'route' - }); - finalAssertExports.hasMethod(route, 'match', { - moduleName: 'workbox-routing', - className: 'Router', - funcName: 'registerRoute', - paramName: 'route' - }); - finalAssertExports.isType(route.handler, 'object', { - moduleName: 'workbox-routing', - className: 'Router', - funcName: 'registerRoute', - paramName: 'route' - }); - finalAssertExports.hasMethod(route.handler, 'handle', { - moduleName: 'workbox-routing', - className: 'Router', - funcName: 'registerRoute', - paramName: 'route.handler' - }); - finalAssertExports.isType(route.method, 'string', { - moduleName: 'workbox-routing', - className: 'Router', - funcName: 'registerRoute', - paramName: 'route.method' - }); - } - if (!this._routes.has(route.method)) { - this._routes.set(route.method, []); - } - // Give precedence to all of the earlier routes by adding this additional - // route to the end of the array. - this._routes.get(route.method).push(route); - } - /** - * Unregisters a route with the router. - * - * @param {workbox-routing.Route} route The route to unregister. - */ - unregisterRoute(route) { - if (!this._routes.has(route.method)) { - throw new WorkboxError('unregister-route-but-not-found-with-method', { - method: route.method - }); - } - const routeIndex = this._routes.get(route.method).indexOf(route); - if (routeIndex > -1) { - this._routes.get(route.method).splice(routeIndex, 1); - } else { - throw new WorkboxError('unregister-route-route-not-registered'); - } - } - } - - /* - Copyright 2019 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - let defaultRouter; - /** - * Creates a new, singleton Router instance if one does not exist. If one - * does already exist, that instance is returned. - * - * @private - * @return {Router} - */ - const getOrCreateDefaultRouter = () => { - if (!defaultRouter) { - defaultRouter = new Router(); - // The helpers that use the default Router assume these listeners exist. - defaultRouter.addFetchListener(); - defaultRouter.addCacheListener(); - } - return defaultRouter; - }; - - /* - Copyright 2019 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * Easily register a RegExp, string, or function with a caching - * strategy to a singleton Router instance. - * - * This method will generate a Route for you if needed and - * call {@link workbox-routing.Router#registerRoute}. - * - * @param {RegExp|string|workbox-routing.Route~matchCallback|workbox-routing.Route} capture - * If the capture param is a `Route`, all other arguments will be ignored. - * @param {workbox-routing~handlerCallback} [handler] A callback - * function that returns a Promise resulting in a Response. This parameter - * is required if `capture` is not a `Route` object. - * @param {string} [method='GET'] The HTTP method to match the Route - * against. - * @return {workbox-routing.Route} The generated `Route`. - * - * @memberof workbox-routing - */ - function registerRoute(capture, handler, method) { - let route; - if (typeof capture === 'string') { - const captureUrl = new URL(capture, location.href); - { - if (!(capture.startsWith('/') || capture.startsWith('http'))) { - throw new WorkboxError('invalid-string', { - moduleName: 'workbox-routing', - funcName: 'registerRoute', - paramName: 'capture' - }); - } - // We want to check if Express-style wildcards are in the pathname only. - // TODO: Remove this log message in v4. - const valueToCheck = capture.startsWith('http') ? captureUrl.pathname : capture; - // See https://github.com/pillarjs/path-to-regexp#parameters - const wildcards = '[*:?+]'; - if (new RegExp(`${wildcards}`).exec(valueToCheck)) { - logger.debug(`The '$capture' parameter contains an Express-style wildcard ` + `character (${wildcards}). Strings are now always interpreted as ` + `exact matches; use a RegExp for partial or wildcard matches.`); - } - } - const matchCallback = ({ - url - }) => { - { - if (url.pathname === captureUrl.pathname && url.origin !== captureUrl.origin) { - logger.debug(`${capture} only partially matches the cross-origin URL ` + `${url.toString()}. This route will only handle cross-origin requests ` + `if they match the entire URL.`); - } - } - return url.href === captureUrl.href; - }; - // If `capture` is a string then `handler` and `method` must be present. - route = new Route(matchCallback, handler, method); - } else if (capture instanceof RegExp) { - // If `capture` is a `RegExp` then `handler` and `method` must be present. - route = new RegExpRoute(capture, handler, method); - } else if (typeof capture === 'function') { - // If `capture` is a function then `handler` and `method` must be present. - route = new Route(capture, handler, method); - } else if (capture instanceof Route) { - route = capture; - } else { - throw new WorkboxError('unsupported-route-type', { - moduleName: 'workbox-routing', - funcName: 'registerRoute', - paramName: 'capture' - }); - } - const defaultRouter = getOrCreateDefaultRouter(); - defaultRouter.registerRoute(route); - return route; - } - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - const _cacheNameDetails = { - googleAnalytics: 'googleAnalytics', - precache: 'precache-v2', - prefix: 'workbox', - runtime: 'runtime', - suffix: typeof registration !== 'undefined' ? registration.scope : '' - }; - const _createCacheName = cacheName => { - return [_cacheNameDetails.prefix, cacheName, _cacheNameDetails.suffix].filter(value => value && value.length > 0).join('-'); - }; - const eachCacheNameDetail = fn => { - for (const key of Object.keys(_cacheNameDetails)) { - fn(key); - } - }; - const cacheNames = { - updateDetails: details => { - eachCacheNameDetail(key => { - if (typeof details[key] === 'string') { - _cacheNameDetails[key] = details[key]; - } - }); - }, - getGoogleAnalyticsName: userCacheName => { - return userCacheName || _createCacheName(_cacheNameDetails.googleAnalytics); - }, - getPrecacheName: userCacheName => { - return userCacheName || _createCacheName(_cacheNameDetails.precache); - }, - getPrefix: () => { - return _cacheNameDetails.prefix; - }, - getRuntimeName: userCacheName => { - return userCacheName || _createCacheName(_cacheNameDetails.runtime); - }, - getSuffix: () => { - return _cacheNameDetails.suffix; - } - }; - - /* - Copyright 2020 Google LLC - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * A utility method that makes it easier to use `event.waitUntil` with - * async functions and return the result. - * - * @param {ExtendableEvent} event - * @param {Function} asyncFn - * @return {Function} - * @private - */ - function waitUntil(event, asyncFn) { - const returnPromise = asyncFn(); - event.waitUntil(returnPromise); - return returnPromise; - } - - // @ts-ignore - try { - self['workbox:precaching:7.3.0'] && _(); - } catch (e) {} - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - // Name of the search parameter used to store revision info. - const REVISION_SEARCH_PARAM = '__WB_REVISION__'; - /** - * Converts a manifest entry into a versioned URL suitable for precaching. - * - * @param {Object|string} entry - * @return {string} A URL with versioning info. - * - * @private - * @memberof workbox-precaching - */ - function createCacheKey(entry) { - if (!entry) { - throw new WorkboxError('add-to-cache-list-unexpected-type', { - entry - }); - } - // If a precache manifest entry is a string, it's assumed to be a versioned - // URL, like '/app.abcd1234.js'. Return as-is. - if (typeof entry === 'string') { - const urlObject = new URL(entry, location.href); - return { - cacheKey: urlObject.href, - url: urlObject.href - }; - } - const { - revision, - url - } = entry; - if (!url) { - throw new WorkboxError('add-to-cache-list-unexpected-type', { - entry - }); - } - // If there's just a URL and no revision, then it's also assumed to be a - // versioned URL. - if (!revision) { - const urlObject = new URL(url, location.href); - return { - cacheKey: urlObject.href, - url: urlObject.href - }; - } - // Otherwise, construct a properly versioned URL using the custom Workbox - // search parameter along with the revision info. - const cacheKeyURL = new URL(url, location.href); - const originalURL = new URL(url, location.href); - cacheKeyURL.searchParams.set(REVISION_SEARCH_PARAM, revision); - return { - cacheKey: cacheKeyURL.href, - url: originalURL.href - }; - } - - /* - Copyright 2020 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * A plugin, designed to be used with PrecacheController, to determine the - * of assets that were updated (or not updated) during the install event. - * - * @private - */ - class PrecacheInstallReportPlugin { - constructor() { - this.updatedURLs = []; - this.notUpdatedURLs = []; - this.handlerWillStart = async ({ - request, - state - }) => { - // TODO: `state` should never be undefined... - if (state) { - state.originalRequest = request; - } - }; - this.cachedResponseWillBeUsed = async ({ - event, - state, - cachedResponse - }) => { - if (event.type === 'install') { - if (state && state.originalRequest && state.originalRequest instanceof Request) { - // TODO: `state` should never be undefined... - const url = state.originalRequest.url; - if (cachedResponse) { - this.notUpdatedURLs.push(url); - } else { - this.updatedURLs.push(url); - } - } - } - return cachedResponse; - }; - } - } - - /* - Copyright 2020 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * A plugin, designed to be used with PrecacheController, to translate URLs into - * the corresponding cache key, based on the current revision info. - * - * @private - */ - class PrecacheCacheKeyPlugin { - constructor({ - precacheController - }) { - this.cacheKeyWillBeUsed = async ({ - request, - params - }) => { - // Params is type any, can't change right now. - /* eslint-disable */ - const cacheKey = (params === null || params === void 0 ? void 0 : params.cacheKey) || this._precacheController.getCacheKeyForURL(request.url); - /* eslint-enable */ - return cacheKey ? new Request(cacheKey, { - headers: request.headers - }) : request; - }; - this._precacheController = precacheController; - } - } - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * @param {string} groupTitle - * @param {Array} deletedURLs - * - * @private - */ - const logGroup = (groupTitle, deletedURLs) => { - logger.groupCollapsed(groupTitle); - for (const url of deletedURLs) { - logger.log(url); - } - logger.groupEnd(); - }; - /** - * @param {Array} deletedURLs - * - * @private - * @memberof workbox-precaching - */ - function printCleanupDetails(deletedURLs) { - const deletionCount = deletedURLs.length; - if (deletionCount > 0) { - logger.groupCollapsed(`During precaching cleanup, ` + `${deletionCount} cached ` + `request${deletionCount === 1 ? ' was' : 's were'} deleted.`); - logGroup('Deleted Cache Requests', deletedURLs); - logger.groupEnd(); - } - } - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * @param {string} groupTitle - * @param {Array} urls - * - * @private - */ - function _nestedGroup(groupTitle, urls) { - if (urls.length === 0) { - return; - } - logger.groupCollapsed(groupTitle); - for (const url of urls) { - logger.log(url); - } - logger.groupEnd(); - } - /** - * @param {Array} urlsToPrecache - * @param {Array} urlsAlreadyPrecached - * - * @private - * @memberof workbox-precaching - */ - function printInstallDetails(urlsToPrecache, urlsAlreadyPrecached) { - const precachedCount = urlsToPrecache.length; - const alreadyPrecachedCount = urlsAlreadyPrecached.length; - if (precachedCount || alreadyPrecachedCount) { - let message = `Precaching ${precachedCount} file${precachedCount === 1 ? '' : 's'}.`; - if (alreadyPrecachedCount > 0) { - message += ` ${alreadyPrecachedCount} ` + `file${alreadyPrecachedCount === 1 ? ' is' : 's are'} already cached.`; - } - logger.groupCollapsed(message); - _nestedGroup(`View newly precached URLs.`, urlsToPrecache); - _nestedGroup(`View previously precached URLs.`, urlsAlreadyPrecached); - logger.groupEnd(); - } - } - - /* - Copyright 2019 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - let supportStatus; - /** - * A utility function that determines whether the current browser supports - * constructing a new `Response` from a `response.body` stream. - * - * @return {boolean} `true`, if the current browser can successfully - * construct a `Response` from a `response.body` stream, `false` otherwise. - * - * @private - */ - function canConstructResponseFromBodyStream() { - if (supportStatus === undefined) { - const testResponse = new Response(''); - if ('body' in testResponse) { - try { - new Response(testResponse.body); - supportStatus = true; - } catch (error) { - supportStatus = false; - } - } - supportStatus = false; - } - return supportStatus; - } - - /* - Copyright 2019 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * Allows developers to copy a response and modify its `headers`, `status`, - * or `statusText` values (the values settable via a - * [`ResponseInit`]{@link https://developer.mozilla.org/en-US/docs/Web/API/Response/Response#Syntax} - * object in the constructor). - * To modify these values, pass a function as the second argument. That - * function will be invoked with a single object with the response properties - * `{headers, status, statusText}`. The return value of this function will - * be used as the `ResponseInit` for the new `Response`. To change the values - * either modify the passed parameter(s) and return it, or return a totally - * new object. - * - * This method is intentionally limited to same-origin responses, regardless of - * whether CORS was used or not. - * - * @param {Response} response - * @param {Function} modifier - * @memberof workbox-core - */ - async function copyResponse(response, modifier) { - let origin = null; - // If response.url isn't set, assume it's cross-origin and keep origin null. - if (response.url) { - const responseURL = new URL(response.url); - origin = responseURL.origin; - } - if (origin !== self.location.origin) { - throw new WorkboxError('cross-origin-copy-response', { - origin - }); - } - const clonedResponse = response.clone(); - // Create a fresh `ResponseInit` object by cloning the headers. - const responseInit = { - headers: new Headers(clonedResponse.headers), - status: clonedResponse.status, - statusText: clonedResponse.statusText - }; - // Apply any user modifications. - const modifiedResponseInit = modifier ? modifier(responseInit) : responseInit; - // Create the new response from the body stream and `ResponseInit` - // modifications. Note: not all browsers support the Response.body stream, - // so fall back to reading the entire body into memory as a blob. - const body = canConstructResponseFromBodyStream() ? clonedResponse.body : await clonedResponse.blob(); - return new Response(body, modifiedResponseInit); - } - - /* - Copyright 2020 Google LLC - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - function stripParams(fullURL, ignoreParams) { - const strippedURL = new URL(fullURL); - for (const param of ignoreParams) { - strippedURL.searchParams.delete(param); - } - return strippedURL.href; - } - /** - * Matches an item in the cache, ignoring specific URL params. This is similar - * to the `ignoreSearch` option, but it allows you to ignore just specific - * params (while continuing to match on the others). - * - * @private - * @param {Cache} cache - * @param {Request} request - * @param {Object} matchOptions - * @param {Array} ignoreParams - * @return {Promise} - */ - async function cacheMatchIgnoreParams(cache, request, ignoreParams, matchOptions) { - const strippedRequestURL = stripParams(request.url, ignoreParams); - // If the request doesn't include any ignored params, match as normal. - if (request.url === strippedRequestURL) { - return cache.match(request, matchOptions); - } - // Otherwise, match by comparing keys - const keysOptions = Object.assign(Object.assign({}, matchOptions), { - ignoreSearch: true - }); - const cacheKeys = await cache.keys(request, keysOptions); - for (const cacheKey of cacheKeys) { - const strippedCacheKeyURL = stripParams(cacheKey.url, ignoreParams); - if (strippedRequestURL === strippedCacheKeyURL) { - return cache.match(cacheKey, matchOptions); - } - } - return; - } - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * The Deferred class composes Promises in a way that allows for them to be - * resolved or rejected from outside the constructor. In most cases promises - * should be used directly, but Deferreds can be necessary when the logic to - * resolve a promise must be separate. - * - * @private - */ - class Deferred { - /** - * Creates a promise and exposes its resolve and reject functions as methods. - */ - constructor() { - this.promise = new Promise((resolve, reject) => { - this.resolve = resolve; - this.reject = reject; - }); - } - } - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - // Callbacks to be executed whenever there's a quota error. - // Can't change Function type right now. - // eslint-disable-next-line @typescript-eslint/ban-types - const quotaErrorCallbacks = new Set(); - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * Runs all of the callback functions, one at a time sequentially, in the order - * in which they were registered. - * - * @memberof workbox-core - * @private - */ - async function executeQuotaErrorCallbacks() { - { - logger.log(`About to run ${quotaErrorCallbacks.size} ` + `callbacks to clean up caches.`); - } - for (const callback of quotaErrorCallbacks) { - await callback(); - { - logger.log(callback, 'is complete.'); - } - } - { - logger.log('Finished running callbacks.'); - } - } - - /* - Copyright 2019 Google LLC - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * Returns a promise that resolves and the passed number of milliseconds. - * This utility is an async/await-friendly version of `setTimeout`. - * - * @param {number} ms - * @return {Promise} - * @private - */ - function timeout(ms) { - return new Promise(resolve => setTimeout(resolve, ms)); - } - - // @ts-ignore - try { - self['workbox:strategies:7.3.0'] && _(); - } catch (e) {} - - /* - Copyright 2020 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - function toRequest(input) { - return typeof input === 'string' ? new Request(input) : input; - } - /** - * A class created every time a Strategy instance calls - * {@link workbox-strategies.Strategy~handle} or - * {@link workbox-strategies.Strategy~handleAll} that wraps all fetch and - * cache actions around plugin callbacks and keeps track of when the strategy - * is "done" (i.e. all added `event.waitUntil()` promises have resolved). - * - * @memberof workbox-strategies - */ - class StrategyHandler { - /** - * Creates a new instance associated with the passed strategy and event - * that's handling the request. - * - * The constructor also initializes the state that will be passed to each of - * the plugins handling this request. - * - * @param {workbox-strategies.Strategy} strategy - * @param {Object} options - * @param {Request|string} options.request A request to run this strategy for. - * @param {ExtendableEvent} options.event The event associated with the - * request. - * @param {URL} [options.url] - * @param {*} [options.params] The return value from the - * {@link workbox-routing~matchCallback} (if applicable). - */ - constructor(strategy, options) { - this._cacheKeys = {}; - /** - * The request the strategy is performing (passed to the strategy's - * `handle()` or `handleAll()` method). - * @name request - * @instance - * @type {Request} - * @memberof workbox-strategies.StrategyHandler - */ - /** - * The event associated with this request. - * @name event - * @instance - * @type {ExtendableEvent} - * @memberof workbox-strategies.StrategyHandler - */ - /** - * A `URL` instance of `request.url` (if passed to the strategy's - * `handle()` or `handleAll()` method). - * Note: the `url` param will be present if the strategy was invoked - * from a workbox `Route` object. - * @name url - * @instance - * @type {URL|undefined} - * @memberof workbox-strategies.StrategyHandler - */ - /** - * A `param` value (if passed to the strategy's - * `handle()` or `handleAll()` method). - * Note: the `param` param will be present if the strategy was invoked - * from a workbox `Route` object and the - * {@link workbox-routing~matchCallback} returned - * a truthy value (it will be that value). - * @name params - * @instance - * @type {*|undefined} - * @memberof workbox-strategies.StrategyHandler - */ - { - finalAssertExports.isInstance(options.event, ExtendableEvent, { - moduleName: 'workbox-strategies', - className: 'StrategyHandler', - funcName: 'constructor', - paramName: 'options.event' - }); - } - Object.assign(this, options); - this.event = options.event; - this._strategy = strategy; - this._handlerDeferred = new Deferred(); - this._extendLifetimePromises = []; - // Copy the plugins list (since it's mutable on the strategy), - // so any mutations don't affect this handler instance. - this._plugins = [...strategy.plugins]; - this._pluginStateMap = new Map(); - for (const plugin of this._plugins) { - this._pluginStateMap.set(plugin, {}); - } - this.event.waitUntil(this._handlerDeferred.promise); - } - /** - * Fetches a given request (and invokes any applicable plugin callback - * methods) using the `fetchOptions` (for non-navigation requests) and - * `plugins` defined on the `Strategy` object. - * - * The following plugin lifecycle methods are invoked when using this method: - * - `requestWillFetch()` - * - `fetchDidSucceed()` - * - `fetchDidFail()` - * - * @param {Request|string} input The URL or request to fetch. - * @return {Promise} - */ - async fetch(input) { - const { - event - } = this; - let request = toRequest(input); - if (request.mode === 'navigate' && event instanceof FetchEvent && event.preloadResponse) { - const possiblePreloadResponse = await event.preloadResponse; - if (possiblePreloadResponse) { - { - logger.log(`Using a preloaded navigation response for ` + `'${getFriendlyURL(request.url)}'`); - } - return possiblePreloadResponse; - } - } - // If there is a fetchDidFail plugin, we need to save a clone of the - // original request before it's either modified by a requestWillFetch - // plugin or before the original request's body is consumed via fetch(). - const originalRequest = this.hasCallback('fetchDidFail') ? request.clone() : null; - try { - for (const cb of this.iterateCallbacks('requestWillFetch')) { - request = await cb({ - request: request.clone(), - event - }); - } - } catch (err) { - if (err instanceof Error) { - throw new WorkboxError('plugin-error-request-will-fetch', { - thrownErrorMessage: err.message - }); - } - } - // The request can be altered by plugins with `requestWillFetch` making - // the original request (most likely from a `fetch` event) different - // from the Request we make. Pass both to `fetchDidFail` to aid debugging. - const pluginFilteredRequest = request.clone(); - try { - let fetchResponse; - // See https://github.com/GoogleChrome/workbox/issues/1796 - fetchResponse = await fetch(request, request.mode === 'navigate' ? undefined : this._strategy.fetchOptions); - if ("development" !== 'production') { - logger.debug(`Network request for ` + `'${getFriendlyURL(request.url)}' returned a response with ` + `status '${fetchResponse.status}'.`); - } - for (const callback of this.iterateCallbacks('fetchDidSucceed')) { - fetchResponse = await callback({ - event, - request: pluginFilteredRequest, - response: fetchResponse - }); - } - return fetchResponse; - } catch (error) { - { - logger.log(`Network request for ` + `'${getFriendlyURL(request.url)}' threw an error.`, error); - } - // `originalRequest` will only exist if a `fetchDidFail` callback - // is being used (see above). - if (originalRequest) { - await this.runCallbacks('fetchDidFail', { - error: error, - event, - originalRequest: originalRequest.clone(), - request: pluginFilteredRequest.clone() - }); - } - throw error; - } - } - /** - * Calls `this.fetch()` and (in the background) runs `this.cachePut()` on - * the response generated by `this.fetch()`. - * - * The call to `this.cachePut()` automatically invokes `this.waitUntil()`, - * so you do not have to manually call `waitUntil()` on the event. - * - * @param {Request|string} input The request or URL to fetch and cache. - * @return {Promise} - */ - async fetchAndCachePut(input) { - const response = await this.fetch(input); - const responseClone = response.clone(); - void this.waitUntil(this.cachePut(input, responseClone)); - return response; - } - /** - * Matches a request from the cache (and invokes any applicable plugin - * callback methods) using the `cacheName`, `matchOptions`, and `plugins` - * defined on the strategy object. - * - * The following plugin lifecycle methods are invoked when using this method: - * - cacheKeyWillBeUsed() - * - cachedResponseWillBeUsed() - * - * @param {Request|string} key The Request or URL to use as the cache key. - * @return {Promise} A matching response, if found. - */ - async cacheMatch(key) { - const request = toRequest(key); - let cachedResponse; - const { - cacheName, - matchOptions - } = this._strategy; - const effectiveRequest = await this.getCacheKey(request, 'read'); - const multiMatchOptions = Object.assign(Object.assign({}, matchOptions), { - cacheName - }); - cachedResponse = await caches.match(effectiveRequest, multiMatchOptions); - { - if (cachedResponse) { - logger.debug(`Found a cached response in '${cacheName}'.`); - } else { - logger.debug(`No cached response found in '${cacheName}'.`); - } - } - for (const callback of this.iterateCallbacks('cachedResponseWillBeUsed')) { - cachedResponse = (await callback({ - cacheName, - matchOptions, - cachedResponse, - request: effectiveRequest, - event: this.event - })) || undefined; - } - return cachedResponse; - } - /** - * Puts a request/response pair in the cache (and invokes any applicable - * plugin callback methods) using the `cacheName` and `plugins` defined on - * the strategy object. - * - * The following plugin lifecycle methods are invoked when using this method: - * - cacheKeyWillBeUsed() - * - cacheWillUpdate() - * - cacheDidUpdate() - * - * @param {Request|string} key The request or URL to use as the cache key. - * @param {Response} response The response to cache. - * @return {Promise} `false` if a cacheWillUpdate caused the response - * not be cached, and `true` otherwise. - */ - async cachePut(key, response) { - const request = toRequest(key); - // Run in the next task to avoid blocking other cache reads. - // https://github.com/w3c/ServiceWorker/issues/1397 - await timeout(0); - const effectiveRequest = await this.getCacheKey(request, 'write'); - { - if (effectiveRequest.method && effectiveRequest.method !== 'GET') { - throw new WorkboxError('attempt-to-cache-non-get-request', { - url: getFriendlyURL(effectiveRequest.url), - method: effectiveRequest.method - }); - } - // See https://github.com/GoogleChrome/workbox/issues/2818 - const vary = response.headers.get('Vary'); - if (vary) { - logger.debug(`The response for ${getFriendlyURL(effectiveRequest.url)} ` + `has a 'Vary: ${vary}' header. ` + `Consider setting the {ignoreVary: true} option on your strategy ` + `to ensure cache matching and deletion works as expected.`); - } - } - if (!response) { - { - logger.error(`Cannot cache non-existent response for ` + `'${getFriendlyURL(effectiveRequest.url)}'.`); - } - throw new WorkboxError('cache-put-with-no-response', { - url: getFriendlyURL(effectiveRequest.url) - }); - } - const responseToCache = await this._ensureResponseSafeToCache(response); - if (!responseToCache) { - { - logger.debug(`Response '${getFriendlyURL(effectiveRequest.url)}' ` + `will not be cached.`, responseToCache); - } - return false; - } - const { - cacheName, - matchOptions - } = this._strategy; - const cache = await self.caches.open(cacheName); - const hasCacheUpdateCallback = this.hasCallback('cacheDidUpdate'); - const oldResponse = hasCacheUpdateCallback ? await cacheMatchIgnoreParams( - // TODO(philipwalton): the `__WB_REVISION__` param is a precaching - // feature. Consider into ways to only add this behavior if using - // precaching. - cache, effectiveRequest.clone(), ['__WB_REVISION__'], matchOptions) : null; - { - logger.debug(`Updating the '${cacheName}' cache with a new Response ` + `for ${getFriendlyURL(effectiveRequest.url)}.`); - } - try { - await cache.put(effectiveRequest, hasCacheUpdateCallback ? responseToCache.clone() : responseToCache); - } catch (error) { - if (error instanceof Error) { - // See https://developer.mozilla.org/en-US/docs/Web/API/DOMException#exception-QuotaExceededError - if (error.name === 'QuotaExceededError') { - await executeQuotaErrorCallbacks(); - } - throw error; - } - } - for (const callback of this.iterateCallbacks('cacheDidUpdate')) { - await callback({ - cacheName, - oldResponse, - newResponse: responseToCache.clone(), - request: effectiveRequest, - event: this.event - }); - } - return true; - } - /** - * Checks the list of plugins for the `cacheKeyWillBeUsed` callback, and - * executes any of those callbacks found in sequence. The final `Request` - * object returned by the last plugin is treated as the cache key for cache - * reads and/or writes. If no `cacheKeyWillBeUsed` plugin callbacks have - * been registered, the passed request is returned unmodified - * - * @param {Request} request - * @param {string} mode - * @return {Promise} - */ - async getCacheKey(request, mode) { - const key = `${request.url} | ${mode}`; - if (!this._cacheKeys[key]) { - let effectiveRequest = request; - for (const callback of this.iterateCallbacks('cacheKeyWillBeUsed')) { - effectiveRequest = toRequest(await callback({ - mode, - request: effectiveRequest, - event: this.event, - // params has a type any can't change right now. - params: this.params // eslint-disable-line - })); - } - this._cacheKeys[key] = effectiveRequest; - } - return this._cacheKeys[key]; - } - /** - * Returns true if the strategy has at least one plugin with the given - * callback. - * - * @param {string} name The name of the callback to check for. - * @return {boolean} - */ - hasCallback(name) { - for (const plugin of this._strategy.plugins) { - if (name in plugin) { - return true; - } - } - return false; - } - /** - * Runs all plugin callbacks matching the given name, in order, passing the - * given param object (merged ith the current plugin state) as the only - * argument. - * - * Note: since this method runs all plugins, it's not suitable for cases - * where the return value of a callback needs to be applied prior to calling - * the next callback. See - * {@link workbox-strategies.StrategyHandler#iterateCallbacks} - * below for how to handle that case. - * - * @param {string} name The name of the callback to run within each plugin. - * @param {Object} param The object to pass as the first (and only) param - * when executing each callback. This object will be merged with the - * current plugin state prior to callback execution. - */ - async runCallbacks(name, param) { - for (const callback of this.iterateCallbacks(name)) { - // TODO(philipwalton): not sure why `any` is needed. It seems like - // this should work with `as WorkboxPluginCallbackParam[C]`. - await callback(param); - } - } - /** - * Accepts a callback and returns an iterable of matching plugin callbacks, - * where each callback is wrapped with the current handler state (i.e. when - * you call each callback, whatever object parameter you pass it will - * be merged with the plugin's current state). - * - * @param {string} name The name fo the callback to run - * @return {Array} - */ - *iterateCallbacks(name) { - for (const plugin of this._strategy.plugins) { - if (typeof plugin[name] === 'function') { - const state = this._pluginStateMap.get(plugin); - const statefulCallback = param => { - const statefulParam = Object.assign(Object.assign({}, param), { - state - }); - // TODO(philipwalton): not sure why `any` is needed. It seems like - // this should work with `as WorkboxPluginCallbackParam[C]`. - return plugin[name](statefulParam); - }; - yield statefulCallback; - } - } - } - /** - * Adds a promise to the - * [extend lifetime promises]{@link https://w3c.github.io/ServiceWorker/#extendableevent-extend-lifetime-promises} - * of the event associated with the request being handled (usually a - * `FetchEvent`). - * - * Note: you can await - * {@link workbox-strategies.StrategyHandler~doneWaiting} - * to know when all added promises have settled. - * - * @param {Promise} promise A promise to add to the extend lifetime promises - * of the event that triggered the request. - */ - waitUntil(promise) { - this._extendLifetimePromises.push(promise); - return promise; - } - /** - * Returns a promise that resolves once all promises passed to - * {@link workbox-strategies.StrategyHandler~waitUntil} - * have settled. - * - * Note: any work done after `doneWaiting()` settles should be manually - * passed to an event's `waitUntil()` method (not this handler's - * `waitUntil()` method), otherwise the service worker thread may be killed - * prior to your work completing. - */ - async doneWaiting() { - while (this._extendLifetimePromises.length) { - const promises = this._extendLifetimePromises.splice(0); - const result = await Promise.allSettled(promises); - const firstRejection = result.find(i => i.status === 'rejected'); - if (firstRejection) { - throw firstRejection.reason; - } - } - } - /** - * Stops running the strategy and immediately resolves any pending - * `waitUntil()` promises. - */ - destroy() { - this._handlerDeferred.resolve(null); - } - /** - * This method will call cacheWillUpdate on the available plugins (or use - * status === 200) to determine if the Response is safe and valid to cache. - * - * @param {Request} options.request - * @param {Response} options.response - * @return {Promise} - * - * @private - */ - async _ensureResponseSafeToCache(response) { - let responseToCache = response; - let pluginsUsed = false; - for (const callback of this.iterateCallbacks('cacheWillUpdate')) { - responseToCache = (await callback({ - request: this.request, - response: responseToCache, - event: this.event - })) || undefined; - pluginsUsed = true; - if (!responseToCache) { - break; - } - } - if (!pluginsUsed) { - if (responseToCache && responseToCache.status !== 200) { - responseToCache = undefined; - } - { - if (responseToCache) { - if (responseToCache.status !== 200) { - if (responseToCache.status === 0) { - logger.warn(`The response for '${this.request.url}' ` + `is an opaque response. The caching strategy that you're ` + `using will not cache opaque responses by default.`); - } else { - logger.debug(`The response for '${this.request.url}' ` + `returned a status code of '${response.status}' and won't ` + `be cached as a result.`); - } - } - } - } - } - return responseToCache; - } - } - - /* - Copyright 2020 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * An abstract base class that all other strategy classes must extend from: - * - * @memberof workbox-strategies - */ - class Strategy { - /** - * Creates a new instance of the strategy and sets all documented option - * properties as public instance properties. - * - * Note: if a custom strategy class extends the base Strategy class and does - * not need more than these properties, it does not need to define its own - * constructor. - * - * @param {Object} [options] - * @param {string} [options.cacheName] Cache name to store and retrieve - * requests. Defaults to the cache names provided by - * {@link workbox-core.cacheNames}. - * @param {Array} [options.plugins] [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} - * to use in conjunction with this caching strategy. - * @param {Object} [options.fetchOptions] Values passed along to the - * [`init`](https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters) - * of [non-navigation](https://github.com/GoogleChrome/workbox/issues/1796) - * `fetch()` requests made by this strategy. - * @param {Object} [options.matchOptions] The - * [`CacheQueryOptions`]{@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions} - * for any `cache.match()` or `cache.put()` calls made by this strategy. - */ - constructor(options = {}) { - /** - * Cache name to store and retrieve - * requests. Defaults to the cache names provided by - * {@link workbox-core.cacheNames}. - * - * @type {string} - */ - this.cacheName = cacheNames.getRuntimeName(options.cacheName); - /** - * The list - * [Plugins]{@link https://developers.google.com/web/tools/workbox/guides/using-plugins} - * used by this strategy. - * - * @type {Array} - */ - this.plugins = options.plugins || []; - /** - * Values passed along to the - * [`init`]{@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters} - * of all fetch() requests made by this strategy. - * - * @type {Object} - */ - this.fetchOptions = options.fetchOptions; - /** - * The - * [`CacheQueryOptions`]{@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions} - * for any `cache.match()` or `cache.put()` calls made by this strategy. - * - * @type {Object} - */ - this.matchOptions = options.matchOptions; - } - /** - * Perform a request strategy and returns a `Promise` that will resolve with - * a `Response`, invoking all relevant plugin callbacks. - * - * When a strategy instance is registered with a Workbox - * {@link workbox-routing.Route}, this method is automatically - * called when the route matches. - * - * Alternatively, this method can be used in a standalone `FetchEvent` - * listener by passing it to `event.respondWith()`. - * - * @param {FetchEvent|Object} options A `FetchEvent` or an object with the - * properties listed below. - * @param {Request|string} options.request A request to run this strategy for. - * @param {ExtendableEvent} options.event The event associated with the - * request. - * @param {URL} [options.url] - * @param {*} [options.params] - */ - handle(options) { - const [responseDone] = this.handleAll(options); - return responseDone; - } - /** - * Similar to {@link workbox-strategies.Strategy~handle}, but - * instead of just returning a `Promise` that resolves to a `Response` it - * it will return an tuple of `[response, done]` promises, where the former - * (`response`) is equivalent to what `handle()` returns, and the latter is a - * Promise that will resolve once any promises that were added to - * `event.waitUntil()` as part of performing the strategy have completed. - * - * You can await the `done` promise to ensure any extra work performed by - * the strategy (usually caching responses) completes successfully. - * - * @param {FetchEvent|Object} options A `FetchEvent` or an object with the - * properties listed below. - * @param {Request|string} options.request A request to run this strategy for. - * @param {ExtendableEvent} options.event The event associated with the - * request. - * @param {URL} [options.url] - * @param {*} [options.params] - * @return {Array} A tuple of [response, done] - * promises that can be used to determine when the response resolves as - * well as when the handler has completed all its work. - */ - handleAll(options) { - // Allow for flexible options to be passed. - if (options instanceof FetchEvent) { - options = { - event: options, - request: options.request - }; - } - const event = options.event; - const request = typeof options.request === 'string' ? new Request(options.request) : options.request; - const params = 'params' in options ? options.params : undefined; - const handler = new StrategyHandler(this, { - event, - request, - params - }); - const responseDone = this._getResponse(handler, request, event); - const handlerDone = this._awaitComplete(responseDone, handler, request, event); - // Return an array of promises, suitable for use with Promise.all(). - return [responseDone, handlerDone]; - } - async _getResponse(handler, request, event) { - await handler.runCallbacks('handlerWillStart', { - event, - request - }); - let response = undefined; - try { - response = await this._handle(request, handler); - // The "official" Strategy subclasses all throw this error automatically, - // but in case a third-party Strategy doesn't, ensure that we have a - // consistent failure when there's no response or an error response. - if (!response || response.type === 'error') { - throw new WorkboxError('no-response', { - url: request.url - }); - } - } catch (error) { - if (error instanceof Error) { - for (const callback of handler.iterateCallbacks('handlerDidError')) { - response = await callback({ - error, - event, - request - }); - if (response) { - break; - } - } - } - if (!response) { - throw error; - } else { - logger.log(`While responding to '${getFriendlyURL(request.url)}', ` + `an ${error instanceof Error ? error.toString() : ''} error occurred. Using a fallback response provided by ` + `a handlerDidError plugin.`); - } - } - for (const callback of handler.iterateCallbacks('handlerWillRespond')) { - response = await callback({ - event, - request, - response - }); - } - return response; - } - async _awaitComplete(responseDone, handler, request, event) { - let response; - let error; - try { - response = await responseDone; - } catch (error) { - // Ignore errors, as response errors should be caught via the `response` - // promise above. The `done` promise will only throw for errors in - // promises passed to `handler.waitUntil()`. - } - try { - await handler.runCallbacks('handlerDidRespond', { - event, - request, - response - }); - await handler.doneWaiting(); - } catch (waitUntilError) { - if (waitUntilError instanceof Error) { - error = waitUntilError; - } - } - await handler.runCallbacks('handlerDidComplete', { - event, - request, - response, - error: error - }); - handler.destroy(); - if (error) { - throw error; - } - } - } - /** - * Classes extending the `Strategy` based class should implement this method, - * and leverage the {@link workbox-strategies.StrategyHandler} - * arg to perform all fetching and cache logic, which will ensure all relevant - * cache, cache options, fetch options and plugins are used (per the current - * strategy instance). - * - * @name _handle - * @instance - * @abstract - * @function - * @param {Request} request - * @param {workbox-strategies.StrategyHandler} handler - * @return {Promise} - * - * @memberof workbox-strategies.Strategy - */ - - /* - Copyright 2020 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * A {@link workbox-strategies.Strategy} implementation - * specifically designed to work with - * {@link workbox-precaching.PrecacheController} - * to both cache and fetch precached assets. - * - * Note: an instance of this class is created automatically when creating a - * `PrecacheController`; it's generally not necessary to create this yourself. - * - * @extends workbox-strategies.Strategy - * @memberof workbox-precaching - */ - class PrecacheStrategy extends Strategy { - /** - * - * @param {Object} [options] - * @param {string} [options.cacheName] Cache name to store and retrieve - * requests. Defaults to the cache names provided by - * {@link workbox-core.cacheNames}. - * @param {Array} [options.plugins] {@link https://developers.google.com/web/tools/workbox/guides/using-plugins|Plugins} - * to use in conjunction with this caching strategy. - * @param {Object} [options.fetchOptions] Values passed along to the - * {@link https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/fetch#Parameters|init} - * of all fetch() requests made by this strategy. - * @param {Object} [options.matchOptions] The - * {@link https://w3c.github.io/ServiceWorker/#dictdef-cachequeryoptions|CacheQueryOptions} - * for any `cache.match()` or `cache.put()` calls made by this strategy. - * @param {boolean} [options.fallbackToNetwork=true] Whether to attempt to - * get the response from the network if there's a precache miss. - */ - constructor(options = {}) { - options.cacheName = cacheNames.getPrecacheName(options.cacheName); - super(options); - this._fallbackToNetwork = options.fallbackToNetwork === false ? false : true; - // Redirected responses cannot be used to satisfy a navigation request, so - // any redirected response must be "copied" rather than cloned, so the new - // response doesn't contain the `redirected` flag. See: - // https://bugs.chromium.org/p/chromium/issues/detail?id=669363&desc=2#c1 - this.plugins.push(PrecacheStrategy.copyRedirectedCacheableResponsesPlugin); - } - /** - * @private - * @param {Request|string} request A request to run this strategy for. - * @param {workbox-strategies.StrategyHandler} handler The event that - * triggered the request. - * @return {Promise} - */ - async _handle(request, handler) { - const response = await handler.cacheMatch(request); - if (response) { - return response; - } - // If this is an `install` event for an entry that isn't already cached, - // then populate the cache. - if (handler.event && handler.event.type === 'install') { - return await this._handleInstall(request, handler); - } - // Getting here means something went wrong. An entry that should have been - // precached wasn't found in the cache. - return await this._handleFetch(request, handler); - } - async _handleFetch(request, handler) { - let response; - const params = handler.params || {}; - // Fall back to the network if we're configured to do so. - if (this._fallbackToNetwork) { - { - logger.warn(`The precached response for ` + `${getFriendlyURL(request.url)} in ${this.cacheName} was not ` + `found. Falling back to the network.`); - } - const integrityInManifest = params.integrity; - const integrityInRequest = request.integrity; - const noIntegrityConflict = !integrityInRequest || integrityInRequest === integrityInManifest; - // Do not add integrity if the original request is no-cors - // See https://github.com/GoogleChrome/workbox/issues/3096 - response = await handler.fetch(new Request(request, { - integrity: request.mode !== 'no-cors' ? integrityInRequest || integrityInManifest : undefined - })); - // It's only "safe" to repair the cache if we're using SRI to guarantee - // that the response matches the precache manifest's expectations, - // and there's either a) no integrity property in the incoming request - // or b) there is an integrity, and it matches the precache manifest. - // See https://github.com/GoogleChrome/workbox/issues/2858 - // Also if the original request users no-cors we don't use integrity. - // See https://github.com/GoogleChrome/workbox/issues/3096 - if (integrityInManifest && noIntegrityConflict && request.mode !== 'no-cors') { - this._useDefaultCacheabilityPluginIfNeeded(); - const wasCached = await handler.cachePut(request, response.clone()); - { - if (wasCached) { - logger.log(`A response for ${getFriendlyURL(request.url)} ` + `was used to "repair" the precache.`); - } - } - } - } else { - // This shouldn't normally happen, but there are edge cases: - // https://github.com/GoogleChrome/workbox/issues/1441 - throw new WorkboxError('missing-precache-entry', { - cacheName: this.cacheName, - url: request.url - }); - } - { - const cacheKey = params.cacheKey || (await handler.getCacheKey(request, 'read')); - // Workbox is going to handle the route. - // print the routing details to the console. - logger.groupCollapsed(`Precaching is responding to: ` + getFriendlyURL(request.url)); - logger.log(`Serving the precached url: ${getFriendlyURL(cacheKey instanceof Request ? cacheKey.url : cacheKey)}`); - logger.groupCollapsed(`View request details here.`); - logger.log(request); - logger.groupEnd(); - logger.groupCollapsed(`View response details here.`); - logger.log(response); - logger.groupEnd(); - logger.groupEnd(); - } - return response; - } - async _handleInstall(request, handler) { - this._useDefaultCacheabilityPluginIfNeeded(); - const response = await handler.fetch(request); - // Make sure we defer cachePut() until after we know the response - // should be cached; see https://github.com/GoogleChrome/workbox/issues/2737 - const wasCached = await handler.cachePut(request, response.clone()); - if (!wasCached) { - // Throwing here will lead to the `install` handler failing, which - // we want to do if *any* of the responses aren't safe to cache. - throw new WorkboxError('bad-precaching-response', { - url: request.url, - status: response.status - }); - } - return response; - } - /** - * This method is complex, as there a number of things to account for: - * - * The `plugins` array can be set at construction, and/or it might be added to - * to at any time before the strategy is used. - * - * At the time the strategy is used (i.e. during an `install` event), there - * needs to be at least one plugin that implements `cacheWillUpdate` in the - * array, other than `copyRedirectedCacheableResponsesPlugin`. - * - * - If this method is called and there are no suitable `cacheWillUpdate` - * plugins, we need to add `defaultPrecacheCacheabilityPlugin`. - * - * - If this method is called and there is exactly one `cacheWillUpdate`, then - * we don't have to do anything (this might be a previously added - * `defaultPrecacheCacheabilityPlugin`, or it might be a custom plugin). - * - * - If this method is called and there is more than one `cacheWillUpdate`, - * then we need to check if one is `defaultPrecacheCacheabilityPlugin`. If so, - * we need to remove it. (This situation is unlikely, but it could happen if - * the strategy is used multiple times, the first without a `cacheWillUpdate`, - * and then later on after manually adding a custom `cacheWillUpdate`.) - * - * See https://github.com/GoogleChrome/workbox/issues/2737 for more context. - * - * @private - */ - _useDefaultCacheabilityPluginIfNeeded() { - let defaultPluginIndex = null; - let cacheWillUpdatePluginCount = 0; - for (const [index, plugin] of this.plugins.entries()) { - // Ignore the copy redirected plugin when determining what to do. - if (plugin === PrecacheStrategy.copyRedirectedCacheableResponsesPlugin) { - continue; - } - // Save the default plugin's index, in case it needs to be removed. - if (plugin === PrecacheStrategy.defaultPrecacheCacheabilityPlugin) { - defaultPluginIndex = index; - } - if (plugin.cacheWillUpdate) { - cacheWillUpdatePluginCount++; - } - } - if (cacheWillUpdatePluginCount === 0) { - this.plugins.push(PrecacheStrategy.defaultPrecacheCacheabilityPlugin); - } else if (cacheWillUpdatePluginCount > 1 && defaultPluginIndex !== null) { - // Only remove the default plugin; multiple custom plugins are allowed. - this.plugins.splice(defaultPluginIndex, 1); - } - // Nothing needs to be done if cacheWillUpdatePluginCount is 1 - } - } - PrecacheStrategy.defaultPrecacheCacheabilityPlugin = { - async cacheWillUpdate({ - response - }) { - if (!response || response.status >= 400) { - return null; - } - return response; - } - }; - PrecacheStrategy.copyRedirectedCacheableResponsesPlugin = { - async cacheWillUpdate({ - response - }) { - return response.redirected ? await copyResponse(response) : response; - } - }; - - /* - Copyright 2019 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * Performs efficient precaching of assets. - * - * @memberof workbox-precaching - */ - class PrecacheController { - /** - * Create a new PrecacheController. - * - * @param {Object} [options] - * @param {string} [options.cacheName] The cache to use for precaching. - * @param {string} [options.plugins] Plugins to use when precaching as well - * as responding to fetch events for precached assets. - * @param {boolean} [options.fallbackToNetwork=true] Whether to attempt to - * get the response from the network if there's a precache miss. - */ - constructor({ - cacheName, - plugins = [], - fallbackToNetwork = true - } = {}) { - this._urlsToCacheKeys = new Map(); - this._urlsToCacheModes = new Map(); - this._cacheKeysToIntegrities = new Map(); - this._strategy = new PrecacheStrategy({ - cacheName: cacheNames.getPrecacheName(cacheName), - plugins: [...plugins, new PrecacheCacheKeyPlugin({ - precacheController: this - })], - fallbackToNetwork - }); - // Bind the install and activate methods to the instance. - this.install = this.install.bind(this); - this.activate = this.activate.bind(this); - } - /** - * @type {workbox-precaching.PrecacheStrategy} The strategy created by this controller and - * used to cache assets and respond to fetch events. - */ - get strategy() { - return this._strategy; - } - /** - * Adds items to the precache list, removing any duplicates and - * stores the files in the - * {@link workbox-core.cacheNames|"precache cache"} when the service - * worker installs. - * - * This method can be called multiple times. - * - * @param {Array} [entries=[]] Array of entries to precache. - */ - precache(entries) { - this.addToCacheList(entries); - if (!this._installAndActiveListenersAdded) { - self.addEventListener('install', this.install); - self.addEventListener('activate', this.activate); - this._installAndActiveListenersAdded = true; - } - } - /** - * This method will add items to the precache list, removing duplicates - * and ensuring the information is valid. - * - * @param {Array} entries - * Array of entries to precache. - */ - addToCacheList(entries) { - { - finalAssertExports.isArray(entries, { - moduleName: 'workbox-precaching', - className: 'PrecacheController', - funcName: 'addToCacheList', - paramName: 'entries' - }); - } - const urlsToWarnAbout = []; - for (const entry of entries) { - // See https://github.com/GoogleChrome/workbox/issues/2259 - if (typeof entry === 'string') { - urlsToWarnAbout.push(entry); - } else if (entry && entry.revision === undefined) { - urlsToWarnAbout.push(entry.url); - } - const { - cacheKey, - url - } = createCacheKey(entry); - const cacheMode = typeof entry !== 'string' && entry.revision ? 'reload' : 'default'; - if (this._urlsToCacheKeys.has(url) && this._urlsToCacheKeys.get(url) !== cacheKey) { - throw new WorkboxError('add-to-cache-list-conflicting-entries', { - firstEntry: this._urlsToCacheKeys.get(url), - secondEntry: cacheKey - }); - } - if (typeof entry !== 'string' && entry.integrity) { - if (this._cacheKeysToIntegrities.has(cacheKey) && this._cacheKeysToIntegrities.get(cacheKey) !== entry.integrity) { - throw new WorkboxError('add-to-cache-list-conflicting-integrities', { - url - }); - } - this._cacheKeysToIntegrities.set(cacheKey, entry.integrity); - } - this._urlsToCacheKeys.set(url, cacheKey); - this._urlsToCacheModes.set(url, cacheMode); - if (urlsToWarnAbout.length > 0) { - const warningMessage = `Workbox is precaching URLs without revision ` + `info: ${urlsToWarnAbout.join(', ')}\nThis is generally NOT safe. ` + `Learn more at https://bit.ly/wb-precache`; - { - logger.warn(warningMessage); - } - } - } - } - /** - * Precaches new and updated assets. Call this method from the service worker - * install event. - * - * Note: this method calls `event.waitUntil()` for you, so you do not need - * to call it yourself in your event handlers. - * - * @param {ExtendableEvent} event - * @return {Promise} - */ - install(event) { - // waitUntil returns Promise - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return waitUntil(event, async () => { - const installReportPlugin = new PrecacheInstallReportPlugin(); - this.strategy.plugins.push(installReportPlugin); - // Cache entries one at a time. - // See https://github.com/GoogleChrome/workbox/issues/2528 - for (const [url, cacheKey] of this._urlsToCacheKeys) { - const integrity = this._cacheKeysToIntegrities.get(cacheKey); - const cacheMode = this._urlsToCacheModes.get(url); - const request = new Request(url, { - integrity, - cache: cacheMode, - credentials: 'same-origin' - }); - await Promise.all(this.strategy.handleAll({ - params: { - cacheKey - }, - request, - event - })); - } - const { - updatedURLs, - notUpdatedURLs - } = installReportPlugin; - { - printInstallDetails(updatedURLs, notUpdatedURLs); - } - return { - updatedURLs, - notUpdatedURLs - }; - }); - } - /** - * Deletes assets that are no longer present in the current precache manifest. - * Call this method from the service worker activate event. - * - * Note: this method calls `event.waitUntil()` for you, so you do not need - * to call it yourself in your event handlers. - * - * @param {ExtendableEvent} event - * @return {Promise} - */ - activate(event) { - // waitUntil returns Promise - // eslint-disable-next-line @typescript-eslint/no-unsafe-return - return waitUntil(event, async () => { - const cache = await self.caches.open(this.strategy.cacheName); - const currentlyCachedRequests = await cache.keys(); - const expectedCacheKeys = new Set(this._urlsToCacheKeys.values()); - const deletedURLs = []; - for (const request of currentlyCachedRequests) { - if (!expectedCacheKeys.has(request.url)) { - await cache.delete(request); - deletedURLs.push(request.url); - } - } - { - printCleanupDetails(deletedURLs); - } - return { - deletedURLs - }; - }); - } - /** - * Returns a mapping of a precached URL to the corresponding cache key, taking - * into account the revision information for the URL. - * - * @return {Map} A URL to cache key mapping. - */ - getURLsToCacheKeys() { - return this._urlsToCacheKeys; - } - /** - * Returns a list of all the URLs that have been precached by the current - * service worker. - * - * @return {Array} The precached URLs. - */ - getCachedURLs() { - return [...this._urlsToCacheKeys.keys()]; - } - /** - * Returns the cache key used for storing a given URL. If that URL is - * unversioned, like `/index.html', then the cache key will be the original - * URL with a search parameter appended to it. - * - * @param {string} url A URL whose cache key you want to look up. - * @return {string} The versioned URL that corresponds to a cache key - * for the original URL, or undefined if that URL isn't precached. - */ - getCacheKeyForURL(url) { - const urlObject = new URL(url, location.href); - return this._urlsToCacheKeys.get(urlObject.href); - } - /** - * @param {string} url A cache key whose SRI you want to look up. - * @return {string} The subresource integrity associated with the cache key, - * or undefined if it's not set. - */ - getIntegrityForCacheKey(cacheKey) { - return this._cacheKeysToIntegrities.get(cacheKey); - } - /** - * This acts as a drop-in replacement for - * [`cache.match()`](https://developer.mozilla.org/en-US/docs/Web/API/Cache/match) - * with the following differences: - * - * - It knows what the name of the precache is, and only checks in that cache. - * - It allows you to pass in an "original" URL without versioning parameters, - * and it will automatically look up the correct cache key for the currently - * active revision of that URL. - * - * E.g., `matchPrecache('index.html')` will find the correct precached - * response for the currently active service worker, even if the actual cache - * key is `'/index.html?__WB_REVISION__=1234abcd'`. - * - * @param {string|Request} request The key (without revisioning parameters) - * to look up in the precache. - * @return {Promise} - */ - async matchPrecache(request) { - const url = request instanceof Request ? request.url : request; - const cacheKey = this.getCacheKeyForURL(url); - if (cacheKey) { - const cache = await self.caches.open(this.strategy.cacheName); - return cache.match(cacheKey); - } - return undefined; - } - /** - * Returns a function that looks up `url` in the precache (taking into - * account revision information), and returns the corresponding `Response`. - * - * @param {string} url The precached URL which will be used to lookup the - * `Response`. - * @return {workbox-routing~handlerCallback} - */ - createHandlerBoundToURL(url) { - const cacheKey = this.getCacheKeyForURL(url); - if (!cacheKey) { - throw new WorkboxError('non-precached-url', { - url - }); - } - return options => { - options.request = new Request(url); - options.params = Object.assign({ - cacheKey - }, options.params); - return this.strategy.handle(options); - }; - } - } - - /* - Copyright 2019 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - let precacheController; - /** - * @return {PrecacheController} - * @private - */ - const getOrCreatePrecacheController = () => { - if (!precacheController) { - precacheController = new PrecacheController(); - } - return precacheController; - }; - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * Removes any URL search parameters that should be ignored. - * - * @param {URL} urlObject The original URL. - * @param {Array} ignoreURLParametersMatching RegExps to test against - * each search parameter name. Matches mean that the search parameter should be - * ignored. - * @return {URL} The URL with any ignored search parameters removed. - * - * @private - * @memberof workbox-precaching - */ - function removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching = []) { - // Convert the iterable into an array at the start of the loop to make sure - // deletion doesn't mess up iteration. - for (const paramName of [...urlObject.searchParams.keys()]) { - if (ignoreURLParametersMatching.some(regExp => regExp.test(paramName))) { - urlObject.searchParams.delete(paramName); - } - } - return urlObject; - } - - /* - Copyright 2019 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * Generator function that yields possible variations on the original URL to - * check, one at a time. - * - * @param {string} url - * @param {Object} options - * - * @private - * @memberof workbox-precaching - */ - function* generateURLVariations(url, { - ignoreURLParametersMatching = [/^utm_/, /^fbclid$/], - directoryIndex = 'index.html', - cleanURLs = true, - urlManipulation - } = {}) { - const urlObject = new URL(url, location.href); - urlObject.hash = ''; - yield urlObject.href; - const urlWithoutIgnoredParams = removeIgnoredSearchParams(urlObject, ignoreURLParametersMatching); - yield urlWithoutIgnoredParams.href; - if (directoryIndex && urlWithoutIgnoredParams.pathname.endsWith('/')) { - const directoryURL = new URL(urlWithoutIgnoredParams.href); - directoryURL.pathname += directoryIndex; - yield directoryURL.href; - } - if (cleanURLs) { - const cleanURL = new URL(urlWithoutIgnoredParams.href); - cleanURL.pathname += '.html'; - yield cleanURL.href; - } - if (urlManipulation) { - const additionalURLs = urlManipulation({ - url: urlObject - }); - for (const urlToAttempt of additionalURLs) { - yield urlToAttempt.href; - } - } - } - - /* - Copyright 2020 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * A subclass of {@link workbox-routing.Route} that takes a - * {@link workbox-precaching.PrecacheController} - * instance and uses it to match incoming requests and handle fetching - * responses from the precache. - * - * @memberof workbox-precaching - * @extends workbox-routing.Route - */ - class PrecacheRoute extends Route { - /** - * @param {PrecacheController} precacheController A `PrecacheController` - * instance used to both match requests and respond to fetch events. - * @param {Object} [options] Options to control how requests are matched - * against the list of precached URLs. - * @param {string} [options.directoryIndex=index.html] The `directoryIndex` will - * check cache entries for a URLs ending with '/' to see if there is a hit when - * appending the `directoryIndex` value. - * @param {Array} [options.ignoreURLParametersMatching=[/^utm_/, /^fbclid$/]] An - * array of regex's to remove search params when looking for a cache match. - * @param {boolean} [options.cleanURLs=true] The `cleanURLs` option will - * check the cache for the URL with a `.html` added to the end of the end. - * @param {workbox-precaching~urlManipulation} [options.urlManipulation] - * This is a function that should take a URL and return an array of - * alternative URLs that should be checked for precache matches. - */ - constructor(precacheController, options) { - const match = ({ - request - }) => { - const urlsToCacheKeys = precacheController.getURLsToCacheKeys(); - for (const possibleURL of generateURLVariations(request.url, options)) { - const cacheKey = urlsToCacheKeys.get(possibleURL); - if (cacheKey) { - const integrity = precacheController.getIntegrityForCacheKey(cacheKey); - return { - cacheKey, - integrity - }; - } - } - { - logger.debug(`Precaching did not find a match for ` + getFriendlyURL(request.url)); - } - return; - }; - super(match, precacheController.strategy); - } - } - - /* - Copyright 2019 Google LLC - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * Add a `fetch` listener to the service worker that will - * respond to - * [network requests]{@link https://developer.mozilla.org/en-US/docs/Web/API/Service_Worker_API/Using_Service_Workers#Custom_responses_to_requests} - * with precached assets. - * - * Requests for assets that aren't precached, the `FetchEvent` will not be - * responded to, allowing the event to fall through to other `fetch` event - * listeners. - * - * @param {Object} [options] See the {@link workbox-precaching.PrecacheRoute} - * options. - * - * @memberof workbox-precaching - */ - function addRoute(options) { - const precacheController = getOrCreatePrecacheController(); - const precacheRoute = new PrecacheRoute(precacheController, options); - registerRoute(precacheRoute); - } - - /* - Copyright 2019 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * Adds items to the precache list, removing any duplicates and - * stores the files in the - * {@link workbox-core.cacheNames|"precache cache"} when the service - * worker installs. - * - * This method can be called multiple times. - * - * Please note: This method **will not** serve any of the cached files for you. - * It only precaches files. To respond to a network request you call - * {@link workbox-precaching.addRoute}. - * - * If you have a single array of files to precache, you can just call - * {@link workbox-precaching.precacheAndRoute}. - * - * @param {Array} [entries=[]] Array of entries to precache. - * - * @memberof workbox-precaching - */ - function precache(entries) { - const precacheController = getOrCreatePrecacheController(); - precacheController.precache(entries); - } - - /* - Copyright 2019 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * This method will add entries to the precache list and add a route to - * respond to fetch events. - * - * This is a convenience method that will call - * {@link workbox-precaching.precache} and - * {@link workbox-precaching.addRoute} in a single call. - * - * @param {Array} entries Array of entries to precache. - * @param {Object} [options] See the - * {@link workbox-precaching.PrecacheRoute} options. - * - * @memberof workbox-precaching - */ - function precacheAndRoute(entries, options) { - precache(entries); - addRoute(options); - } - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - const SUBSTRING_TO_FIND = '-precache-'; - /** - * Cleans up incompatible precaches that were created by older versions of - * Workbox, by a service worker registered under the current scope. - * - * This is meant to be called as part of the `activate` event. - * - * This should be safe to use as long as you don't include `substringToFind` - * (defaulting to `-precache-`) in your non-precache cache names. - * - * @param {string} currentPrecacheName The cache name currently in use for - * precaching. This cache won't be deleted. - * @param {string} [substringToFind='-precache-'] Cache names which include this - * substring will be deleted (excluding `currentPrecacheName`). - * @return {Array} A list of all the cache names that were deleted. - * - * @private - * @memberof workbox-precaching - */ - const deleteOutdatedCaches = async (currentPrecacheName, substringToFind = SUBSTRING_TO_FIND) => { - const cacheNames = await self.caches.keys(); - const cacheNamesToDelete = cacheNames.filter(cacheName => { - return cacheName.includes(substringToFind) && cacheName.includes(self.registration.scope) && cacheName !== currentPrecacheName; - }); - await Promise.all(cacheNamesToDelete.map(cacheName => self.caches.delete(cacheName))); - return cacheNamesToDelete; - }; - - /* - Copyright 2019 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * Adds an `activate` event listener which will clean up incompatible - * precaches that were created by older versions of Workbox. - * - * @memberof workbox-precaching - */ - function cleanupOutdatedCaches() { - // See https://github.com/Microsoft/TypeScript/issues/28357#issuecomment-436484705 - self.addEventListener('activate', event => { - const cacheName = cacheNames.getPrecacheName(); - event.waitUntil(deleteOutdatedCaches(cacheName).then(cachesDeleted => { - { - if (cachesDeleted.length > 0) { - logger.log(`The following out-of-date precaches were cleaned up ` + `automatically:`, cachesDeleted); - } - } - })); - }); - } - - /* - Copyright 2018 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * NavigationRoute makes it easy to create a - * {@link workbox-routing.Route} that matches for browser - * [navigation requests]{@link https://developers.google.com/web/fundamentals/primers/service-workers/high-performance-loading#first_what_are_navigation_requests}. - * - * It will only match incoming Requests whose - * {@link https://fetch.spec.whatwg.org/#concept-request-mode|mode} - * is set to `navigate`. - * - * You can optionally only apply this route to a subset of navigation requests - * by using one or both of the `denylist` and `allowlist` parameters. - * - * @memberof workbox-routing - * @extends workbox-routing.Route - */ - class NavigationRoute extends Route { - /** - * If both `denylist` and `allowlist` are provided, the `denylist` will - * take precedence and the request will not match this route. - * - * The regular expressions in `allowlist` and `denylist` - * are matched against the concatenated - * [`pathname`]{@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/pathname} - * and [`search`]{@link https://developer.mozilla.org/en-US/docs/Web/API/HTMLHyperlinkElementUtils/search} - * portions of the requested URL. - * - * *Note*: These RegExps may be evaluated against every destination URL during - * a navigation. Avoid using - * [complex RegExps](https://github.com/GoogleChrome/workbox/issues/3077), - * or else your users may see delays when navigating your site. - * - * @param {workbox-routing~handlerCallback} handler A callback - * function that returns a Promise resulting in a Response. - * @param {Object} options - * @param {Array} [options.denylist] If any of these patterns match, - * the route will not handle the request (even if a allowlist RegExp matches). - * @param {Array} [options.allowlist=[/./]] If any of these patterns - * match the URL's pathname and search parameter, the route will handle the - * request (assuming the denylist doesn't match). - */ - constructor(handler, { - allowlist = [/./], - denylist = [] - } = {}) { - { - finalAssertExports.isArrayOfClass(allowlist, RegExp, { - moduleName: 'workbox-routing', - className: 'NavigationRoute', - funcName: 'constructor', - paramName: 'options.allowlist' - }); - finalAssertExports.isArrayOfClass(denylist, RegExp, { - moduleName: 'workbox-routing', - className: 'NavigationRoute', - funcName: 'constructor', - paramName: 'options.denylist' - }); - } - super(options => this._match(options), handler); - this._allowlist = allowlist; - this._denylist = denylist; - } - /** - * Routes match handler. - * - * @param {Object} options - * @param {URL} options.url - * @param {Request} options.request - * @return {boolean} - * - * @private - */ - _match({ - url, - request - }) { - if (request && request.mode !== 'navigate') { - return false; - } - const pathnameAndSearch = url.pathname + url.search; - for (const regExp of this._denylist) { - if (regExp.test(pathnameAndSearch)) { - { - logger.log(`The navigation route ${pathnameAndSearch} is not ` + `being used, since the URL matches this denylist pattern: ` + `${regExp.toString()}`); - } - return false; - } - } - if (this._allowlist.some(regExp => regExp.test(pathnameAndSearch))) { - { - logger.debug(`The navigation route ${pathnameAndSearch} ` + `is being used.`); - } - return true; - } - { - logger.log(`The navigation route ${pathnameAndSearch} is not ` + `being used, since the URL being navigated to doesn't ` + `match the allowlist.`); - } - return false; - } - } - - /* - Copyright 2019 Google LLC - - Use of this source code is governed by an MIT-style - license that can be found in the LICENSE file or at - https://opensource.org/licenses/MIT. - */ - /** - * Helper function that calls - * {@link PrecacheController#createHandlerBoundToURL} on the default - * {@link PrecacheController} instance. - * - * If you are creating your own {@link PrecacheController}, then call the - * {@link PrecacheController#createHandlerBoundToURL} on that instance, - * instead of using this function. - * - * @param {string} url The precached URL which will be used to lookup the - * `Response`. - * @param {boolean} [fallbackToNetwork=true] Whether to attempt to get the - * response from the network if there's a precache miss. - * @return {workbox-routing~handlerCallback} - * - * @memberof workbox-precaching - */ - function createHandlerBoundToURL(url) { - const precacheController = getOrCreatePrecacheController(); - return precacheController.createHandlerBoundToURL(url); - } - - exports.NavigationRoute = NavigationRoute; - exports.cleanupOutdatedCaches = cleanupOutdatedCaches; - exports.clientsClaim = clientsClaim; - exports.createHandlerBoundToURL = createHandlerBoundToURL; - exports.precacheAndRoute = precacheAndRoute; - exports.registerRoute = registerRoute; - -}));