feat: add bundled local admin asset and entry

This commit is contained in:
Innei
2022-02-24 17:10:29 +08:00
parent 6fc9594bba
commit 786201dd40
7 changed files with 389 additions and 83 deletions

View File

@@ -64,6 +64,7 @@
}, },
"dependencies": { "dependencies": {
"@algolia/client-search": "*", "@algolia/client-search": "*",
"@innei/class-validator-jsonschema": "3.1.1",
"@nestjs/common": "8.3.1", "@nestjs/common": "8.3.1",
"@nestjs/core": "8.3.1", "@nestjs/core": "8.3.1",
"@nestjs/event-emitter": "1.0.0", "@nestjs/event-emitter": "1.0.0",
@@ -88,7 +89,6 @@
"camelcase-keys": "7.0.2", "camelcase-keys": "7.0.2",
"class-transformer": "0.5.1", "class-transformer": "0.5.1",
"class-validator": "0.13.2", "class-validator": "0.13.2",
"@innei/class-validator-jsonschema": "3.1.1",
"consola": "*", "consola": "*",
"cos-nodejs-sdk-v5": "2.11.6", "cos-nodejs-sdk-v5": "2.11.6",
"dayjs": "1.10.7", "dayjs": "1.10.7",
@@ -102,6 +102,7 @@
"inquirer": "*", "inquirer": "*",
"isbot": "3.4.3", "isbot": "3.4.3",
"js-yaml": "*", "js-yaml": "*",
"jsdom": "19",
"jszip": "3.7.1", "jszip": "3.7.1",
"lodash": "*", "lodash": "*",
"marked": "4.0.12", "marked": "4.0.12",
@@ -140,6 +141,7 @@
"@types/ioredis": "4.28.8", "@types/ioredis": "4.28.8",
"@types/jest": "27.4.1", "@types/jest": "27.4.1",
"@types/js-yaml": "4.0.5", "@types/js-yaml": "4.0.5",
"@types/jsdom": "16.2.14",
"@types/lodash": "4.14.178", "@types/lodash": "4.14.178",
"@types/marked": "4.0.2", "@types/marked": "4.0.2",
"@types/mongoose-paginate-v2": "1.4.3", "@types/mongoose-paginate-v2": "1.4.3",

182
pnpm-lock.yaml generated
View File

@@ -36,6 +36,7 @@ specifiers:
'@types/ioredis': 4.28.8 '@types/ioredis': 4.28.8
'@types/jest': 27.4.1 '@types/jest': 27.4.1
'@types/js-yaml': 4.0.5 '@types/js-yaml': 4.0.5
'@types/jsdom': 16.2.14
'@types/lodash': 4.14.178 '@types/lodash': 4.14.178
'@types/marked': 4.0.2 '@types/marked': 4.0.2
'@types/mongoose-paginate-v2': 1.4.3 '@types/mongoose-paginate-v2': 1.4.3
@@ -72,6 +73,7 @@ specifiers:
isbot: 3.4.3 isbot: 3.4.3
jest: 27.5.1 jest: 27.5.1
js-yaml: '*' js-yaml: '*'
jsdom: '19'
jszip: 3.7.1 jszip: 3.7.1
lint-staged: 12.3.4 lint-staged: 12.3.4
lodash: '*' lodash: '*'
@@ -150,6 +152,7 @@ dependencies:
inquirer: 8.2.0 inquirer: 8.2.0
isbot: 3.4.3 isbot: 3.4.3
js-yaml: 4.1.0 js-yaml: 4.1.0
jsdom: 19.0.0
jszip: 3.7.1 jszip: 3.7.1
lodash: 4.17.21 lodash: 4.17.21
marked: 4.0.12 marked: 4.0.12
@@ -192,6 +195,7 @@ devDependencies:
'@types/ioredis': 4.28.8 '@types/ioredis': 4.28.8
'@types/jest': 27.4.1 '@types/jest': 27.4.1
'@types/js-yaml': 4.0.5 '@types/js-yaml': 4.0.5
'@types/jsdom': 16.2.14
'@types/lodash': 4.14.178 '@types/lodash': 4.14.178
'@types/marked': 4.0.2 '@types/marked': 4.0.2
'@types/mongoose-paginate-v2': 1.4.3 '@types/mongoose-paginate-v2': 1.4.3
@@ -1567,6 +1571,11 @@ packages:
engines: {node: '>= 6'} engines: {node: '>= 6'}
dev: true dev: true
/@tootallnate/once/2.0.0:
resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
engines: {node: '>= 10'}
dev: false
/@trivago/prettier-plugin-sort-imports/3.1.1_prettier@2.5.1: /@trivago/prettier-plugin-sort-imports/3.1.1_prettier@2.5.1:
resolution: {integrity: sha512-T9EJNEOugWts4WxdmpWeY+sp+2fUHhvGh9QSBCowEGJfcbnu355HQRqok5bKwejdieMaI1+uGZhuTNMZwjqOCQ==} resolution: {integrity: sha512-T9EJNEOugWts4WxdmpWeY+sp+2fUHhvGh9QSBCowEGJfcbnu355HQRqok5bKwejdieMaI1+uGZhuTNMZwjqOCQ==}
peerDependencies: peerDependencies:
@@ -1807,6 +1816,14 @@ packages:
resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==} resolution: {integrity: sha512-FhpRzf927MNQdRZP0J5DLIdTXhjLYzeUTmLAu69mnVksLH9CJY3IuSeEgbKUki7GQZm0WqDkGzyxju2EZGD2wA==}
dev: true dev: true
/@types/jsdom/16.2.14:
resolution: {integrity: sha512-6BAy1xXEmMuHeAJ4Fv4yXKwBDTGTOseExKE3OaHiNycdHdZw59KfYzrt0DkDluvwmik1HRt6QS7bImxUmpSy+w==}
dependencies:
'@types/node': 16.11.25
'@types/parse5': 6.0.3
'@types/tough-cookie': 4.0.1
dev: true
/@types/json-schema/7.0.9: /@types/json-schema/7.0.9:
resolution: {integrity: sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==} resolution: {integrity: sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==}
dev: true dev: true
@@ -1875,6 +1892,10 @@ packages:
resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==} resolution: {integrity: sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==}
dev: true dev: true
/@types/parse5/6.0.3:
resolution: {integrity: sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==}
dev: true
/@types/passport-jwt/3.0.6: /@types/passport-jwt/3.0.6:
resolution: {integrity: sha512-cmAAMIRTaEwpqxlrZyiEY9kdibk94gP5KTF8AT1Ra4rWNZYHNMreqhKUEeC5WJtuN5SJZjPQmV+XO2P5PlnvNQ==} resolution: {integrity: sha512-cmAAMIRTaEwpqxlrZyiEY9kdibk94gP5KTF8AT1Ra4rWNZYHNMreqhKUEeC5WJtuN5SJZjPQmV+XO2P5PlnvNQ==}
dependencies: dependencies:
@@ -1928,6 +1949,10 @@ packages:
dev: false dev: false
optional: true optional: true
/@types/tough-cookie/4.0.1:
resolution: {integrity: sha512-Y0K95ThC3esLEYD6ZuqNek29lNX2EM1qxV8y2FTLUB0ff5wWrk7az+mLrnNFUnaXcgKye22+sFBRXOgpPILZNg==}
dev: true
/@types/ua-parser-js/0.7.36: /@types/ua-parser-js/0.7.36:
resolution: {integrity: sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==} resolution: {integrity: sha512-N1rW+njavs70y2cApeIw1vLMYXRwfBy+7trgavGuuTfOd7j1Yh7QTRc/yqsPl6ncokt72ZXuxEU0PiCp9bSwNQ==}
dev: true dev: true
@@ -2254,7 +2279,6 @@ packages:
/abab/2.0.5: /abab/2.0.5:
resolution: {integrity: sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==} resolution: {integrity: sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==}
dev: true
/abbrev/1.1.1: /abbrev/1.1.1:
resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==}
@@ -2276,7 +2300,6 @@ packages:
dependencies: dependencies:
acorn: 7.4.1 acorn: 7.4.1
acorn-walk: 7.2.0 acorn-walk: 7.2.0
dev: true
/acorn-import-assertions/1.8.0_acorn@8.7.0: /acorn-import-assertions/1.8.0_acorn@8.7.0:
resolution: {integrity: sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==} resolution: {integrity: sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw==}
@@ -2297,7 +2320,6 @@ packages:
/acorn-walk/7.2.0: /acorn-walk/7.2.0:
resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==} resolution: {integrity: sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==}
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
dev: true
/acorn-walk/8.1.1: /acorn-walk/8.1.1:
resolution: {integrity: sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w==} resolution: {integrity: sha512-FbJdceMlPHEAWJOILDk1fXD8lnTlEIWFkqtfk+MvmL5q/qlHfN7GEHcsFZWt/Tea9jRNPWUZG4G976nqAAmU9w==}
@@ -2308,13 +2330,11 @@ packages:
resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==} resolution: {integrity: sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==}
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
hasBin: true hasBin: true
dev: true
/acorn/8.7.0: /acorn/8.7.0:
resolution: {integrity: sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==} resolution: {integrity: sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==}
engines: {node: '>=0.4.0'} engines: {node: '>=0.4.0'}
hasBin: true hasBin: true
dev: true
/agent-base/6.0.2: /agent-base/6.0.2:
resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==}
@@ -2763,7 +2783,6 @@ packages:
/browser-process-hrtime/1.0.0: /browser-process-hrtime/1.0.0:
resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==} resolution: {integrity: sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==}
dev: true
/browserslist/4.19.1: /browserslist/4.19.1:
resolution: {integrity: sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==} resolution: {integrity: sha512-u2tbbG5PdKRTUoctO3NBD8FQ5HdPh1ZXPHzp1rwaa5jTc+RV9/+RlWiAIKmjRPQF+xbGM9Kklj5bZQFa2s/38A==}
@@ -3252,18 +3271,20 @@ packages:
/cssom/0.3.8: /cssom/0.3.8:
resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==} resolution: {integrity: sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==}
dev: true
/cssom/0.4.4: /cssom/0.4.4:
resolution: {integrity: sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==} resolution: {integrity: sha512-p3pvU7r1MyyqbTk+WbNJIgJjG2VmTIaB10rI93LzVPrmDJKkzKYMtxxyAvQXR/NS6otuzveI7+7BBq3SjBS2mw==}
dev: true dev: true
/cssom/0.5.0:
resolution: {integrity: sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==}
dev: false
/cssstyle/2.3.0: /cssstyle/2.3.0:
resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==} resolution: {integrity: sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==}
engines: {node: '>=8'} engines: {node: '>=8'}
dependencies: dependencies:
cssom: 0.3.8 cssom: 0.3.8
dev: true
/cwise-compiler/1.1.3: /cwise-compiler/1.1.3:
resolution: {integrity: sha1-9NZnQQ6FDToxOn0tt7HlBbsDTMU=} resolution: {integrity: sha1-9NZnQQ6FDToxOn0tt7HlBbsDTMU=}
@@ -3291,6 +3312,15 @@ packages:
whatwg-url: 8.7.0 whatwg-url: 8.7.0
dev: true dev: true
/data-urls/3.0.1:
resolution: {integrity: sha512-Ds554NeT5Gennfoo9KN50Vh6tpgtvYEwraYjejXnyTpu1C7oXKxdFk75REooENHE8ndTVOJuv+BEs4/J/xcozw==}
engines: {node: '>=12'}
dependencies:
abab: 2.0.5
whatwg-mimetype: 3.0.0
whatwg-url: 10.0.0
dev: false
/dayjs/1.10.7: /dayjs/1.10.7:
resolution: {integrity: sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==} resolution: {integrity: sha512-P6twpd70BcPK34K26uJ1KT3wlhpuOAPoMwJzpsIWUxHZ7wpmbdZL/hQqBDfz7hGurYSa5PhzdhDHtt319hL3ig==}
dev: false dev: false
@@ -3339,7 +3369,6 @@ packages:
/decimal.js/10.3.1: /decimal.js/10.3.1:
resolution: {integrity: sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==} resolution: {integrity: sha512-V0pfhfr8suzyPGOx3nmq4aHqabehUZn6Ch9kyFpV79TGDTWFmHqUqXdabR7QHqxzrYolF4+tVmJhUG4OURg5dQ==}
dev: true
/dedent/0.7.0: /dedent/0.7.0:
resolution: {integrity: sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=} resolution: {integrity: sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=}
@@ -3347,7 +3376,6 @@ packages:
/deep-is/0.1.4: /deep-is/0.1.4:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
dev: true
/deepmerge/4.2.2: /deepmerge/4.2.2:
resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==} resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==}
@@ -3448,6 +3476,13 @@ packages:
webidl-conversions: 5.0.0 webidl-conversions: 5.0.0
dev: true dev: true
/domexception/4.0.0:
resolution: {integrity: sha512-A2is4PLG+eeSfoTMA95/s4pvAoSo2mKtiM5jlHkAVewmiO8ISFTFKZjH7UAM1Atli/OT/7JHOrJRJiMKUZKYBw==}
engines: {node: '>=12'}
dependencies:
webidl-conversions: 7.0.0
dev: false
/domhandler/2.4.2: /domhandler/2.4.2:
resolution: {integrity: sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==} resolution: {integrity: sha512-JiK04h0Ht5u/80fdLMCEmV4zkNh2BcoMFBmZ/91WtYZ8qVXSKjiw7fXMgFPnHcSZgOo3XdinHvmnDUeMf5R4wA==}
dependencies: dependencies:
@@ -3673,7 +3708,6 @@ packages:
optionator: 0.8.3 optionator: 0.8.3
optionalDependencies: optionalDependencies:
source-map: 0.6.1 source-map: 0.6.1
dev: true
/eslint-config-prettier/8.4.0_eslint@8.9.0: /eslint-config-prettier/8.4.0_eslint@8.9.0:
resolution: {integrity: sha512-CFotdUcMY18nGRo5KGsnNxpznzhkopOcOo0InID+sgQssPrzjvsyKZPvOgymTFeHrFuC3Tzdf2YndhXtULK9Iw==} resolution: {integrity: sha512-CFotdUcMY18nGRo5KGsnNxpznzhkopOcOo0InID+sgQssPrzjvsyKZPvOgymTFeHrFuC3Tzdf2YndhXtULK9Iw==}
@@ -3890,7 +3924,6 @@ packages:
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==} resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
engines: {node: '>=4'} engines: {node: '>=4'}
hasBin: true hasBin: true
dev: true
/esquery/1.4.0: /esquery/1.4.0:
resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==} resolution: {integrity: sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==}
@@ -3914,12 +3947,10 @@ packages:
/estraverse/5.3.0: /estraverse/5.3.0:
resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==} resolution: {integrity: sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==}
engines: {node: '>=4.0'} engines: {node: '>=4.0'}
dev: true
/esutils/2.0.3: /esutils/2.0.3:
resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dev: true
/etag/1.8.1: /etag/1.8.1:
resolution: {integrity: sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=} resolution: {integrity: sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=}
@@ -4056,7 +4087,6 @@ packages:
/fast-levenshtein/2.0.6: /fast-levenshtein/2.0.6:
resolution: {integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=} resolution: {integrity: sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=}
dev: true
/fast-redact/3.1.0: /fast-redact/3.1.0:
resolution: {integrity: sha512-dir8LOnvialLxiXDPESMDHGp82CHi6ZEYTVkcvdn5d7psdv9ZkkButXrOeXST4aqreIRR+N7CYlsrwFuorurVg==} resolution: {integrity: sha512-dir8LOnvialLxiXDPESMDHGp82CHi6ZEYTVkcvdn5d7psdv9ZkkButXrOeXST4aqreIRR+N7CYlsrwFuorurVg==}
@@ -4348,6 +4378,15 @@ packages:
combined-stream: 1.0.8 combined-stream: 1.0.8
mime-types: 2.1.34 mime-types: 2.1.34
/form-data/4.0.0:
resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==}
engines: {node: '>= 6'}
dependencies:
asynckit: 0.4.0
combined-stream: 1.0.8
mime-types: 2.1.34
dev: false
/forwarded/0.2.0: /forwarded/0.2.0:
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
engines: {node: '>= 0.6'} engines: {node: '>= 0.6'}
@@ -4669,6 +4708,13 @@ packages:
whatwg-encoding: 1.0.5 whatwg-encoding: 1.0.5
dev: true dev: true
/html-encoding-sniffer/3.0.0:
resolution: {integrity: sha512-oWv4T4yJ52iKrufjnyZPkrN0CH3QnrUqdB6In1g5Fe1mia8GmF36gnfNySxoZtxD5+NmYw1EElVXiBk93UeskA==}
engines: {node: '>=12'}
dependencies:
whatwg-encoding: 2.0.0
dev: false
/html-escaper/2.0.2: /html-escaper/2.0.2:
resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==} resolution: {integrity: sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==}
dev: true dev: true
@@ -4720,6 +4766,17 @@ packages:
- supports-color - supports-color
dev: true dev: true
/http-proxy-agent/5.0.0:
resolution: {integrity: sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==}
engines: {node: '>= 6'}
dependencies:
'@tootallnate/once': 2.0.0
agent-base: 6.0.2
debug: 4.3.3
transitivePeerDependencies:
- supports-color
dev: false
/http-signature/1.2.0: /http-signature/1.2.0:
resolution: {integrity: sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=} resolution: {integrity: sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=}
engines: {node: '>=0.8', npm: '>=1.3.7'} engines: {node: '>=0.8', npm: '>=1.3.7'}
@@ -4760,6 +4817,13 @@ packages:
dependencies: dependencies:
safer-buffer: 2.1.2 safer-buffer: 2.1.2
/iconv-lite/0.6.3:
resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==}
engines: {node: '>=0.10.0'}
dependencies:
safer-buffer: 2.1.2
dev: false
/ieee754/1.2.1: /ieee754/1.2.1:
resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==}
@@ -5004,7 +5068,6 @@ packages:
/is-potential-custom-element-name/1.0.1: /is-potential-custom-element-name/1.0.1:
resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==}
dev: true
/is-regex/1.1.4: /is-regex/1.1.4:
resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==}
@@ -5685,6 +5748,48 @@ packages:
- utf-8-validate - utf-8-validate
dev: true dev: true
/jsdom/19.0.0:
resolution: {integrity: sha512-RYAyjCbxy/vri/CfnjUWJQQtZ3LKlLnDqj+9XLNnJPgEGeirZs3hllKR20re8LUZ6o1b1X4Jat+Qd26zmP41+A==}
engines: {node: '>=12'}
peerDependencies:
canvas: ^2.5.0
peerDependenciesMeta:
canvas:
optional: true
dependencies:
abab: 2.0.5
acorn: 8.7.0
acorn-globals: 6.0.0
cssom: 0.5.0
cssstyle: 2.3.0
data-urls: 3.0.1
decimal.js: 10.3.1
domexception: 4.0.0
escodegen: 2.0.0
form-data: 4.0.0
html-encoding-sniffer: 3.0.0
http-proxy-agent: 5.0.0
https-proxy-agent: 5.0.0
is-potential-custom-element-name: 1.0.1
nwsapi: 2.2.0
parse5: 6.0.1
saxes: 5.0.1
symbol-tree: 3.2.4
tough-cookie: 4.0.0
w3c-hr-time: 1.0.2
w3c-xmlserializer: 3.0.0
webidl-conversions: 7.0.0
whatwg-encoding: 2.0.0
whatwg-mimetype: 3.0.0
whatwg-url: 10.0.0
ws: 8.2.3
xml-name-validator: 4.0.0
transitivePeerDependencies:
- bufferutil
- supports-color
- utf-8-validate
dev: false
/jsesc/2.5.2: /jsesc/2.5.2:
resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==}
engines: {node: '>=4'} engines: {node: '>=4'}
@@ -5827,7 +5932,6 @@ packages:
dependencies: dependencies:
prelude-ls: 1.1.2 prelude-ls: 1.1.2
type-check: 0.3.2 type-check: 0.3.2
dev: true
/levn/0.4.1: /levn/0.4.1:
resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==}
@@ -6540,7 +6644,6 @@ packages:
/nwsapi/2.2.0: /nwsapi/2.2.0:
resolution: {integrity: sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==} resolution: {integrity: sha512-h2AatdwYH+JHiZpv7pt/gSX1XoRGb7L/qSIeuqA6GwYoF9w1vP1cw42TO0aI2pNyshRK5893hNSl+1//vHK7hQ==}
dev: true
/oauth-sign/0.9.0: /oauth-sign/0.9.0:
resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==} resolution: {integrity: sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==}
@@ -6626,7 +6729,6 @@ packages:
prelude-ls: 1.1.2 prelude-ls: 1.1.2
type-check: 0.3.2 type-check: 0.3.2
word-wrap: 1.2.3 word-wrap: 1.2.3
dev: true
/optionator/0.9.1: /optionator/0.9.1:
resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==} resolution: {integrity: sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw==}
@@ -6768,7 +6870,6 @@ packages:
/parse5/6.0.1: /parse5/6.0.1:
resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==}
dev: true
/passport-jwt/4.0.0: /passport-jwt/4.0.0:
resolution: {integrity: sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==} resolution: {integrity: sha512-BwC0n2GP/1hMVjR4QpnvqA61TxenUMlmfNjYNgK0ZAs0HK4SOQkHcSv4L328blNTLtHq7DbmvyNJiH+bn6C5Mg==}
@@ -6901,7 +7002,6 @@ packages:
/prelude-ls/1.1.2: /prelude-ls/1.1.2:
resolution: {integrity: sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=} resolution: {integrity: sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=}
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
dev: true
/prelude-ls/1.2.1: /prelude-ls/1.2.1:
resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==}
@@ -7276,7 +7376,6 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
dependencies: dependencies:
xmlchars: 2.2.0 xmlchars: 2.2.0
dev: true
/schema-utils/2.7.0: /schema-utils/2.7.0:
resolution: {integrity: sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==} resolution: {integrity: sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==}
@@ -7742,7 +7841,6 @@ packages:
/symbol-tree/3.2.4: /symbol-tree/3.2.4:
resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==}
dev: true
/tapable/1.1.3: /tapable/1.1.3:
resolution: {integrity: sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==} resolution: {integrity: sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==}
@@ -7906,7 +8004,6 @@ packages:
psl: 1.8.0 psl: 1.8.0
punycode: 2.1.1 punycode: 2.1.1
universalify: 0.1.2 universalify: 0.1.2
dev: true
/tr46/0.0.3: /tr46/0.0.3:
resolution: {integrity: sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=} resolution: {integrity: sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o=}
@@ -8059,7 +8156,6 @@ packages:
engines: {node: '>= 0.8.0'} engines: {node: '>= 0.8.0'}
dependencies: dependencies:
prelude-ls: 1.1.2 prelude-ls: 1.1.2
dev: true
/type-check/0.4.0: /type-check/0.4.0:
resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==} resolution: {integrity: sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==}
@@ -8133,7 +8229,6 @@ packages:
/universalify/0.1.2: /universalify/0.1.2:
resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
engines: {node: '>= 4.0.0'} engines: {node: '>= 4.0.0'}
dev: true
/universalify/2.0.0: /universalify/2.0.0:
resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==} resolution: {integrity: sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==}
@@ -8207,7 +8302,6 @@ packages:
resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==} resolution: {integrity: sha512-z8P5DvDNjKDoFIHK7q8r8lackT6l+jo/Ye3HOle7l9nICP9lf1Ci25fy9vHd0JOWewkIFzXIEig3TdKT7JQ5fQ==}
dependencies: dependencies:
browser-process-hrtime: 1.0.0 browser-process-hrtime: 1.0.0
dev: true
/w3c-xmlserializer/2.0.0: /w3c-xmlserializer/2.0.0:
resolution: {integrity: sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==} resolution: {integrity: sha512-4tzD0mF8iSiMiNs30BiLO3EpfGLZUT2MSX/G+o7ZywDzliWQ3OPtTZ0PTC3B3ca1UAf4cJMHB+2Bf56EriJuRA==}
@@ -8216,6 +8310,13 @@ packages:
xml-name-validator: 3.0.0 xml-name-validator: 3.0.0
dev: true dev: true
/w3c-xmlserializer/3.0.0:
resolution: {integrity: sha512-3WFqGEgSXIyGhOmAFtlicJNMjEps8b1MG31NCA0/vOF9+nKMUW1ckhi9cnNHmf88Rzw5V+dwIwsm2C7X8k9aQg==}
engines: {node: '>=12'}
dependencies:
xml-name-validator: 4.0.0
dev: false
/walker/1.0.8: /walker/1.0.8:
resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==} resolution: {integrity: sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==}
dependencies: dependencies:
@@ -8309,10 +8410,30 @@ packages:
iconv-lite: 0.4.24 iconv-lite: 0.4.24
dev: true dev: true
/whatwg-encoding/2.0.0:
resolution: {integrity: sha512-p41ogyeMUrw3jWclHWTQg1k05DSVXPLcVxRTYsXUk+ZooOCZLcoYgPZ/HL/D/N+uQPOtcp1me1WhBEaX02mhWg==}
engines: {node: '>=12'}
dependencies:
iconv-lite: 0.6.3
dev: false
/whatwg-mimetype/2.3.0: /whatwg-mimetype/2.3.0:
resolution: {integrity: sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==} resolution: {integrity: sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g==}
dev: true dev: true
/whatwg-mimetype/3.0.0:
resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==}
engines: {node: '>=12'}
dev: false
/whatwg-url/10.0.0:
resolution: {integrity: sha512-CLxxCmdUby142H5FZzn4D8ikO1cmypvXVQktsgosNy4a4BHrDHeciBBGZhb0bNoR5/MltoCatso+vFjjGx8t0w==}
engines: {node: '>=12'}
dependencies:
tr46: 3.0.0
webidl-conversions: 7.0.0
dev: false
/whatwg-url/11.0.0: /whatwg-url/11.0.0:
resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==} resolution: {integrity: sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==}
engines: {node: '>=12'} engines: {node: '>=12'}
@@ -8368,7 +8489,6 @@ packages:
/word-wrap/1.2.3: /word-wrap/1.2.3:
resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==} resolution: {integrity: sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
dev: true
/wrap-ansi/6.2.0: /wrap-ansi/6.2.0:
resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==}
@@ -8429,6 +8549,11 @@ packages:
resolution: {integrity: sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==} resolution: {integrity: sha512-A5CUptxDsvxKJEU3yO6DuWBSJz/qizqzJKOMIfUJHETbBw/sFaDxgd6fxm1ewUaM0jZ444Fc5vC5ROYurg/4Pw==}
dev: true dev: true
/xml-name-validator/4.0.0:
resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==}
engines: {node: '>=12'}
dev: false
/xml2js/0.4.23: /xml2js/0.4.23:
resolution: {integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==} resolution: {integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==}
engines: {node: '>=4.0.0'} engines: {node: '>=4.0.0'}
@@ -8444,7 +8569,6 @@ packages:
/xmlchars/2.2.0: /xmlchars/2.2.0:
resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==} resolution: {integrity: sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==}
dev: true
/xss/1.0.10: /xss/1.0.10:
resolution: {integrity: sha512-qmoqrRksmzqSKvgqzN0055UFWY7OKx1/9JWeRswwEVX9fCG5jcYRxa/A2DHcmZX6VJvjzHRQ2STeeVcQkrmLSw==} resolution: {integrity: sha512-qmoqrRksmzqSKvgqzN0055UFWY7OKx1/9JWeRswwEVX9fCG5jcYRxa/A2DHcmZX6VJvjzHRQ2STeeVcQkrmLSw==}

View File

@@ -44,6 +44,7 @@ import { LoggerModule } from './processors/logger/logger.module'
@Module({ @Module({
imports: [ imports: [
LoggerModule,
DatabaseModule, DatabaseModule,
CacheModule, CacheModule,
@@ -63,12 +64,13 @@ import { LoggerModule } from './processors/logger/logger.module'
OptionModule, OptionModule,
PageModule, PageModule,
PostModule, PostModule,
PTYModule,
ProjectModule, ProjectModule,
PTYModule,
RecentlyModule, RecentlyModule,
SayModule, SayModule,
SearchModule, SearchModule,
SitemapModule, SitemapModule,
SnippetModule,
ToolModule, ToolModule,
UserModule, UserModule,
@@ -76,8 +78,6 @@ import { LoggerModule } from './processors/logger/logger.module'
GatewayModule, GatewayModule,
HelperModule, HelperModule,
LoggerModule,
SnippetModule,
isDev ? DebugModule : null, isDev ? DebugModule : null,
].filter(Boolean), ].filter(Boolean),

View File

@@ -16,3 +16,8 @@ export const LOG_DIR = join(DATA_DIR, 'log')
export const BACKUP_DIR = !isDev export const BACKUP_DIR = !isDev
? join(DATA_DIR, 'backup') ? join(DATA_DIR, 'backup')
: join(TEMP_DIR, 'backup') : join(TEMP_DIR, 'backup')
// 生产环境直接打包到 目录的 admin 下
export const LOCAL_ADMIN_ASSET_PATH = isDev
? join(DATA_DIR, 'admin')
: join(__dirname, './admin')

View File

@@ -3,39 +3,32 @@ import {
Get, Get,
InternalServerErrorException, InternalServerErrorException,
Query, Query,
Req,
Res, Res,
} from '@nestjs/common' } from '@nestjs/common'
import { FastifyReply } from 'fastify' import type { FastifyReply, FastifyRequest } from 'fastify'
import { createReadStream, existsSync } from 'fs'
import fs from 'fs/promises'
import { isNull } from 'lodash' import { isNull } from 'lodash'
import PKG from 'package.json' import PKG from 'package.json'
import { API_VERSION } from '~/app.config' import { extname, join } from 'path'
import { Cookies } from '~/common/decorator/cookie.decorator' import { Cookies } from '~/common/decorator/cookie.decorator'
import { HTTPDecorators } from '~/common/decorator/http.decorator' import { HTTPDecorators } from '~/common/decorator/http.decorator'
import { ApiName } from '~/common/decorator/openapi.decorator' import { ApiName } from '~/common/decorator/openapi.decorator'
import { RedisKeys } from '~/constants/cache.constant' import { RedisKeys } from '~/constants/cache.constant'
import { LOCAL_ADMIN_ASSET_PATH } from '~/constants/path.constant'
import { CacheService } from '~/processors/cache/cache.service' import { CacheService } from '~/processors/cache/cache.service'
import { getRedisKey } from '~/utils/redis.util' import { getRedisKey } from '~/utils/redis.util'
import { dashboard } from '../../../package.json' import { dashboard } from '../../../package.json'
import { ConfigsService } from '../configs/configs.service'
import { InitService } from '../init/init.service'
import { PageProxyDebugDto } from './pageproxy.dto' import { PageProxyDebugDto } from './pageproxy.dto'
interface IInjectableData { import { PageProxyService } from './pageproxy.service'
BASE_API: null | string
WEB_URL: null | string
GATEWAY: null | string
LOGIN_BG: null | string
TITLE: null | string
INIT: null | boolean
}
@Controller('/') @Controller('/')
@ApiName @ApiName
export class PageProxyController { export class PageProxyController {
constructor( constructor(
private readonly configs: ConfigsService,
private readonly initService: InitService,
private readonly cacheService: CacheService, private readonly cacheService: CacheService,
private readonly service: PageProxyService,
) {} ) {}
@Get('/qaqdmin') @Get('/qaqdmin')
@@ -45,11 +38,7 @@ export class PageProxyController {
@Query() query: PageProxyDebugDto, @Query() query: PageProxyDebugDto,
@Res() reply: FastifyReply, @Res() reply: FastifyReply,
) { ) {
const { if ((await this.service.checkCanAccessAdminProxy()) === false) {
adminExtra,
url: { webUrl },
} = await this.configs.waitForConfigReady()
if (!adminExtra.enableAdminProxy && !isDev) {
return reply.type('application/json').status(403).send({ return reply.type('application/json').status(403).send({
message: 'admin proxy not enabled', message: 'admin proxy not enabled',
}) })
@@ -96,13 +85,9 @@ export class PageProxyController {
let latestVersion = '' let latestVersion = ''
if (isNull(adminVersion)) { if (isNull(adminVersion)) {
// tag_name: v3.6.x
try { try {
const { tag_name } = await fetch( latestVersion =
`https://api.github.com/repos/${PKG.dashboard.repo}/releases/latest`, await this.service.getAdminLastestVersionFromGHRelease()
).then((data) => data.json())
latestVersion = tag_name.replace(/^v/, '')
} catch (e) { } catch (e) {
reply.type('application/json').status(500).send({ reply.type('application/json').status(500).send({
message: '从获取 GitHub 获取数据失败, 连接超时', message: '从获取 GitHub 获取数据失败, 连接超时',
@@ -145,31 +130,71 @@ export class PageProxyController {
BASE_API: apiUrl ?? cookies['__apiUrl'], BASE_API: apiUrl ?? cookies['__apiUrl'],
GATEWAY: gatewayUrl ?? cookies['__gatewayUrl'], GATEWAY: gatewayUrl ?? cookies['__gatewayUrl'],
} }
const entry = await this.service.injectAdminEnv(source.text, {
BASE_API: sessionInjectableData.BASE_API,
GATEWAY: sessionInjectableData.GATEWAY,
from: source.from,
})
const entry = source.text.replace(
`<!-- injectable script -->`,
`<script>${`window.pageSource='${
source.from
}';\nwindow.injectData = ${JSON.stringify({
LOGIN_BG: adminExtra.background,
TITLE: adminExtra.title,
WEB_URL: webUrl,
INIT: await this.initService.isInit(),
} as IInjectableData)}`}
${
sessionInjectableData.BASE_API
? `window.injectData.BASE_API = '${sessionInjectableData.BASE_API}'`
: `window.injectData.BASE_API = location.origin + '${
!isDev ? '/api/v' + API_VERSION : ''
}';`
}
${
sessionInjectableData.GATEWAY
? `window.injectData.GATEWAY = '${sessionInjectableData.GATEWAY}';`
: `window.injectData.GATEWAY = location.origin;`
}
</script>`,
)
return reply.type('text/html').send(entry) return reply.type('text/html').send(entry)
} }
@Get('/proxy/qaqdmin')
@HTTPDecorators.Bypass
async getLocalBundledAdmin(@Res() reply: FastifyReply) {
if ((await this.service.checkCanAccessAdminProxy()) === false) {
return reply.type('application/json').status(403).send({
message: 'admin proxy not enabled',
})
}
const isAssetPathIsExist = existsSync(LOCAL_ADMIN_ASSET_PATH)
if (!isAssetPathIsExist) {
reply.send('admin asset not found')
}
try {
const entry = await fs.readFile(
path.join(LOCAL_ADMIN_ASSET_PATH, 'index.html'),
'utf8',
)
reply
.type('text/html')
.send(this.service.rewriteAdminEntryAssetPath(entry))
} catch (e) {
reply.code(500).send({
message: e.message,
})
isDev && console.error(e)
}
}
@Get('/proxy/*')
@HTTPDecorators.Bypass
async proxyAssetRoute(
@Req() request: FastifyRequest,
@Res() reply: FastifyReply,
) {
if ((await this.service.checkCanAccessAdminProxy()) === false) {
return reply.type('application/json').status(403).send({
message: 'admin proxy not enabled, proxy assets is forbidden',
})
}
const url = request.url
const relativePath = url.replace(/^\/proxy\//, '')
const path = join(LOCAL_ADMIN_ASSET_PATH, relativePath)
const isPathExist = existsSync(path)
if (!isPathExist) {
return reply.code(404).send()
}
const stream = createReadStream(path)
const minetype = this.service.getMineTypeByExt(extname(path))
if (minetype) {
reply.type(minetype).send(stream)
} else {
reply.send(stream)
}
}
} }

View File

@@ -1,9 +1,11 @@
import { Module } from '@nestjs/common' import { Module } from '@nestjs/common'
import { InitModule } from '../init/init.module' import { InitModule } from '../init/init.module'
import { PageProxyController } from './pageproxy.controller' import { PageProxyController } from './pageproxy.controller'
import { PageProxyService } from './pageproxy.service'
@Module({ @Module({
controllers: [PageProxyController], controllers: [PageProxyController],
providers: [PageProxyService],
imports: [InitModule], imports: [InitModule],
}) })
export class PageProxyModule {} export class PageProxyModule {}

View File

@@ -0,0 +1,148 @@
import { Injectable, InternalServerErrorException } from '@nestjs/common'
import jsdom from 'jsdom'
import { URL } from 'url'
import PKG from '~/../package.json'
import { API_VERSION } from '~/app.config'
import { ConfigsService } from '../configs/configs.service'
import { InitService } from '../init/init.service'
@Injectable()
export class PageProxyService {
constructor(
private readonly configs: ConfigsService,
private readonly initService: InitService,
) {}
async checkCanAccessAdminProxy() {
const { adminExtra } = await this.configs.waitForConfigReady()
if (!adminExtra.enableAdminProxy && !isDev) {
return false
}
return true
}
/**
* @returns {Promise<string>} version `x.y.z` , not startwith `v`
* @throws {Error}
*/
async getAdminLastestVersionFromGHRelease(): Promise<string> {
// tag_name: v3.6.x
const { tag_name } = await fetch(
`https://api.github.com/repos/${PKG.dashboard.repo}/releases/latest`,
).then((data) => data.json())
return tag_name.replace(/^v/, '')
}
async injectAdminEnv(
htmlEntry: string,
env: {
from?: string
BASE_API?: string
GATEWAY?: string
[key: string]: string
},
) {
const config = await this.configs.waitForConfigReady()
const {
adminExtra,
url: { webUrl },
} = config
const { from, BASE_API, GATEWAY } = env
return htmlEntry.replace(
`<!-- injectable script -->`,
`<script>${`window.pageSource='${
from ?? 'server'
}';\nwindow.injectData = ${JSON.stringify({
LOGIN_BG: adminExtra.background,
TITLE: adminExtra.title,
WEB_URL: webUrl,
INIT: await this.initService.isInit(),
} as IInjectableData)}`}
${
BASE_API
? `window.injectData.BASE_API = '${BASE_API}'`
: `window.injectData.BASE_API = location.origin + '${
!isDev ? '/api/v' + API_VERSION : ''
}';`
}
${
GATEWAY
? `window.injectData.GATEWAY = '${GATEWAY}';`
: `window.injectData.GATEWAY = location.origin;`
}
</script>`,
)
}
rewriteAdminEntryAssetPath(htmlEntry: string) {
if (!htmlEntry) {
throw new InternalServerErrorException('htmlEntry is empty')
}
const dom = new jsdom.JSDOM(htmlEntry)
const window = dom.window
const document = window.document
const $scripts = document.querySelectorAll(
'script[src]',
) as NodeListOf<HTMLScriptElement>
const $links = document.querySelectorAll(
'link[href]',
) as NodeListOf<HTMLLinkElement>
const urlReplacer = (__url: string) => {
let url: URL
try {
const isValidUrl = new URL(__url)
url = isValidUrl
} catch {
url = new URL(__url, 'http://localhost')
}
return url
}
$scripts.forEach(($script) => {
const originSrc = $script.src
const url = urlReplacer(originSrc)
$script.src = path.join('/proxy', url.pathname)
})
$links.forEach(($link) => {
const originHref = $link.href
const url = urlReplacer(originHref)
$link.href = path.join('/proxy', url.pathname)
})
return dom.serialize()
}
getMineTypeByExt(ext: string) {
return {
'.css': 'text/css',
'.js': 'application/javascript',
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.ico': 'image/x-icon',
'.svg': 'image/svg+xml',
'.woff': 'application/font-woff',
'.woff2': 'application/font-woff2',
'.ttf': 'application/font-ttf',
'.eot': 'application/vnd.ms-fontobject',
'.html': 'text/html',
'.xml': 'text/xml',
'.txt': 'text/plain',
'.json': 'application/json',
}[ext]
}
}
export interface IInjectableData {
BASE_API: null | string
WEB_URL: null | string
GATEWAY: null | string
LOGIN_BG: null | string
TITLE: null | string
INIT: null | boolean
}